A Commuter’s Challenge in Suburban Philadelphia

Every morning, Midge, a healthcare worker, embarks on her daily journey from the quiet streets of Pottstown1 in Montgomery County to the bustling corridors of the Hospital of the University of Pennsylvania in Philadelphia. Her commute is more than just a physical journey—it’s a daily ordeal, wrestling with the infrequent and unreliable bus service that connects the suburban sprawl to the urban core. On a good day, Midge waits 30 minutes for Bus 93; on a bad day, the wait can exceed an hour. She must then transfer to the Norristown High Speed Line, extending her total morning commute to over 2.5 hours—five times longer than Philadelphia’s average commute time.2 This inconsistency isn’t just a personal inconvenience; it’s a stark reflection of the broader issues of transit inequities that plague many in the suburbs, where buses are few and far between despite the pressing need.

Midge’s story is not unique in Greater Philadelphia—a region where 58.2 percent of public transit users are women and 66.4 percent are people of color. These individuals predominantly populate essential sectors like healthcare, education, and social assistance which employs 25.6 percent of suburban county workers who depend on public transportation. Despite playing critical roles in their communities, these workers earn median annual earnings approximately $7,673 below the regional average. This economic disparity is exacerbated by the transit challenges they face, where the gap in accessibility and frequency of service widens the divide between different socioeconomic groups. Additionally, a significant portion of the workforce, about 35%, lives below the poverty line, heavily relying on this patchwork public transport system that struggles to meet their daily needs.3

The Importance of Transit for Suburban Communities

Midge’s daily commute sheds light on a more significant issue: the critical role of public transportation in providing access to essential services and economic opportunities, especially in suburban communities. Studies highlight a robust negative correlation between unemployment rates and proximity to transit access. In New York City, neighborhoods with some but limited transit access experienced a significantly higher unemployment rate (12.6%) compared to areas with robust transit options (8.1%). 4 This lack of transit access limits physical and economic mobility, contributing to income inequality and higher public assistance dependency.

Moreover, reliable public transportation is pivotal for healthcare access. The National Health Interview Survey (2002) estimated that 3.6 million people miss non-emergency medical appointments annually due to transportation issues. This issue disproportionately affects communities of color, who rely more heavily on public transportation compared to white populations. 5 Midge’s commute is not just a matter of convenience; it’s about accessing crucial healthcare services that manage chronic conditions and provide necessary treatments.

Transportation also plays a fundamental role in educational access. The “geography of opportunity” significantly shapes educational outcomes through accessible transportation, enabling children and young people to reach schools and participate in extracurricular activities.6 A study in Minneapolis found that high school students with access to an unlimited bus and rail pass attended school more regularly and achieved higher GPAs by 0.23 than students without a pass, 7 highlighting the importance of reliable transit in educational attainment.

Using the latest SEPTA General Transit Feed Specification (GTFS) data8, it reveals that a staggering 80% of SEPTA’s trips are made by bus, showcasing the critical role of bus transit in Philadelphia’s transportation network. This statistic underlines the heavy reliance on buses across the city, not just in suburban areas.

# Import GTFS data
stops <- read.csv("data/google_bus/stops.txt", header = TRUE, sep = ",")
stop_times <- read.csv("data/google_bus/stop_times.txt", header = TRUE, sep = ",")
trips <- read.csv("data/google_bus/trips.txt", header = TRUE, sep = ",")
shapes <- read.csv("data/google_bus/shapes.txt", header = TRUE, sep = ",")
routes <- read.csv("data/google_bus/routes.txt", header = TRUE, sep = ",")
calendar <- read.csv("data/google_bus/calendar.txt", header = TRUE, sep = ",")
calendar_dates <- read.csv("data/google_bus/calendar_dates.txt", header = TRUE, sep = ",")

# Import Swiftly data
swiftly <- st_read("data/SwiftlyShapes/geoJSONs/SEPTASurface_HighResSpeed_v2.json")
# Join stop_times and trips, from now on dat will be our main data set
dat <- left_join(stop_times, trips, by = "trip_id")

# join dat and routes
dat <- left_join(dat, routes, by = "route_id")

#determine route_type
dat <- dat %>%
  mutate(mode = if_else(route_type == 0, "Trolley", ifelse(route_type == 1, "Metro", ifelse(route_type == 3, "Bus", "Trolleybus"))))

# Mode share (not ridership)
dat_trip_by_mode <- dat %>%
  group_by(mode) %>%
  summarise(mode_count = n(), .groups = 'drop') %>%
  mutate(total_count = sum(mode_count),
         mode_share = round(mode_count/sum(mode_count)*100, digits = 2)) %>%
  ungroup() 
  
# # Plot mode share using ggplot2 and the custom palette
ggplot(dat_trip_by_mode, aes(x = mode, y = mode_share, fill = mode)) +
  geom_bar(stat = "identity", width = 0.75) +
  scale_fill_manual(values = bus_revolution_palette(length(unique(dat_trip_by_mode$mode)))) +
  geom_text(aes(label = paste0(mode_share, "% (", mode_count, " trips)")),
            vjust = -0.5, color = "black", size = 2.5) +
  labs(title = "Mode Share by Transit Type",
       x = "Mode",
       y = "Mode Share (%)",
       fill = "Mode",
       caption = "Source: SEPTA GTFS Data 2024") +
  theme_minimal() +
  theme(legend.position = "right",
        plot.title = element_text(hjust = 0.5))

# 
# # total trip bus & trolley bus 1.980.505, total observations 2.026.677
# 
# ggplot() +
#   # Add service period background rectangles with reduced alpha for subtlety
#   geom_rect(data = service_periods, aes(xmin = start_hour, xmax = end_hour, ymin = 0, ymax = max(hourly_trips$number_of_trips), fill = peak_category), alpha = 0.2) +
#   # Add the line plot for weekday trips with adjusted point sizes
#   geom_line(data = hourly_trips %>% filter(final_day_type == "Weekday"), aes(x = hour, y = number_of_trips), color = "#F2AE2E", size = 1) +
#   geom_point(data = hourly_trips %>% filter(final_day_type == "Weekday"), aes(x = hour, y = number_of_trips), color = "#26A699", size = 3) +
#   # Add the line plot for weekend trips with a new color for better differentiation
#   geom_line(data = hourly_trips %>% filter(final_day_type == "Weekend"), aes(x = hour, y = number_of_trips), color = "#0072B2", size = 1) +
#   geom_point(data = hourly_trips %>% filter(final_day_type == "Weekend"), aes(x = hour, y = number_of_trips), color = "#D55E00", size = 3) +
#   # Define scales and labels with appropriate adjustments
#   scale_x_continuous(breaks = 0:23) +
#   scale_y_continuous(labels = scales::comma) +
#   scale_fill_manual(values = service_period_colors) +
#   scale_color_manual(values = c("Weekday" = "#F2AE2E", "Weekend" = "#0072B2")) +
#   labs(title = "Number of Trips by Hour with Service Periods",
#        x = "Hour of Day",
#        y = "Number of Trips",
#        fill = "Service Period",
#        color = "Day Type") +
#   theme_minimal() +
#   theme(legend.position = "bottom",
#         plot.title = element_text(hjust = 0.5))
# CREATE LINE GRAPH OF TRIPS BY SERVICE PERIODS

# Function to normalize times greater than 24:00:00. Important step: check the stop_times$arrival_time and departure_time values if it's greater than 24:00 
normalize_time <- function(time_str) {
  time_parts <- strsplit(time_str, ":")[[1]]
  hours <- as.numeric(time_parts[1])
  minutes <- as.numeric(time_parts[2])
  seconds <- as.numeric(time_parts[3])
  
  if (hours >= 24) {
    hours <- hours - 24
    time_str <- sprintf("%02d:%02d:%02d", hours, minutes, seconds)
  }
  
  return(time_str)
}

#identify peak_pm category 
dat <- dat %>%
  mutate(departure_time = sapply(departure_time, normalize_time), # departure_time's normalized
         departure_time = lubridate::hms(departure_time),
         hour = hour(departure_time),  # Extract hour component for easier condition checking
         peak_category = if_else(hour >= 4 & hour < 6, "Early Morning",
                                    if_else(hour >= 6 & hour < 9, "AM Peak",
                                            if_else(hour >= 9 & hour < 15, "Mid Day",
                                                    if_else(hour >= 15 & hour < 18, "PM Peak",
                                                            if_else(hour >= 18 & hour < 22, "Evening", 
                                                                    ifelse(hour >= 22 & hour < 24, "Late Night", "Owl"))))))) 

# # Check if there are any NA values in the 'departure_time' column
# summarise(dat,
#     na_count = sum(is.na(departure_time)), #Count NA values
#     total_rows = n(),  # Total number of rows for context
#     percentage_na = na_count / total_rows * 100  # Percentage of NA values
#   )

durations <- c("Owl" = 4, "Early Morning" = 2, "AM Peak" = 3, "Mid Day" = 6, "PM Peak" = 3, "Evening" = 4, "Late Night" = 2)

dat_service_period <- dat %>%
  filter(mode %in% c("Bus", "Trolleybus", "Trolley")) %>%
  group_by(peak_category)%>%
  summarise(peak_count = n(), .groups = 'drop') %>%
  mutate(total_count = sum(peak_count),
         peak_share = round(peak_count/sum(peak_count)*100, digits = 2)) %>%
  arrange(factor(peak_category, levels = c("Owl", "Early Morning", "AM Peak", "Mid Day", "PM Peak", "Evening", "Late Night"))) %>%
  ungroup()

# Create a data frame for service periods
service_periods <- data.frame(
  peak_category = c("Owl", "Early Morning", "AM Peak", "Mid Day", "PM Peak", "Evening", "Late Night"),
  start_hour = c(0, 4, 6, 9, 15, 18, 22),
  end_hour = c(4, 6, 9, 15, 18, 22, 24)
)

# CREATE BAR CHART OF TRIPS BY SERVICE TYPES

# Ensure 'calendar' has 'day_type' defined
calendar <- calendar %>%
  mutate(
    day_type = case_when(
      monday == 1 & tuesday == 1 & wednesday == 1 & thursday == 1 & friday == 1 & saturday == 0 & sunday == 0 ~ "Weekday",
      (saturday == 1 | sunday == 1) ~ "Weekend",
      TRUE ~ "irregular"
    )
  )

# Calendar_dates includes 'service_id', 'date', and 'exception_type'
# Ensure 'calendar_dates' has 'day_type' defined based on the date
calendar_dates <- calendar_dates %>%
  filter(exception_type == 1) %>% #we only need exception_type == 1, those added to the service
  mutate(
    date = ymd(date),  # Convert date format if necessary
    day_of_week = wday(date, label = TRUE, week_start = 1),
    day_type = case_when(
      day_of_week %in% c("Mon", "Tue", "Wed", "Thu", "Fri") ~ "Weekday",  # Monday to Friday
      TRUE ~ "Weekend"  # Saturday and Sunday
    )
  )

# Join calendar_dates with calendar
calendar_joined <- calendar_dates %>%
  full_join(calendar, by = "service_id", suffix = c(".dates", ".cal")) %>%
  mutate(
    final_day_type = case_when(
      # Use calendar_dates' day_type if exception_type indicates added service
      exception_type == 1 & day_type.dates == "Weekday" ~ "Weekday",
      exception_type == 1 & day_type.dates == "Weekend" ~ "Weekend",
      # Default to calendar's day_type where there's no specific exception noted
      TRUE ~ day_type.cal
    )
  ) %>%
  select(service_id, final_day_type) %>%
  group_by(service_id, final_day_type) %>%
  summarise(count = n(), .groups = 'drop') %>%
  arrange(service_id, desc(count)) %>%
  distinct(service_id, .keep_all = TRUE) %>% # Make sure no double day types for service ID
  select(-count)
  
dat <- dat %>%
  left_join(calendar_joined, by = "service_id")
# SET UP STOPS CATEGORY. This step is crucial as we'll use stops information and join them for each kind of maps 

# Convert stops data to sf object
stops <- stops %>%
  st_as_sf(coords = c("stop_lon", "stop_lat"), crs = 4326, remove = FALSE)

# Load PA and SEPTA region map for base map
PA <- st_read("data/PaCounty2024_05.geojson")
SEPTA_region_map <- PA[PA$COUNTY_NAM %in% c("MONTGOMERY", "BUCKS", "PHILADELPHIA", "DELAWARE", "CHESTER"), ] %>%
  select(PA_CTY_COD, COUNTY_NAM, FIPS_COUNT)

# Load Center City boundary
center_city <- st_read("data/20240708_CenterCity/CenterCity.shp")

# Ensure all datasets are in the same CRS
SEPTA_region_map <- st_transform(SEPTA_region_map, crs = st_crs(stops))
center_city <- st_transform(center_city, crs = st_crs(stops))

# Perform the spatial intersection for county
stops <- stops %>%
  st_join(SEPTA_region_map, left = TRUE, join = st_intersects) %>%
  rename(county = COUNTY_NAM) %>%
  mutate(center_city = st_within(stops, center_city, sparse = FALSE))%>%
  mutate(center_city = rowSums(center_city) > 0)  # Convert logical matrix to vector

# Categorize the stops
stops <- stops %>%
  mutate(category = case_when(
    county == "PHILADELPHIA" & center_city == TRUE ~ "PHILADELPHIA-Center_City",
    county == "PHILADELPHIA" & center_city == FALSE ~ "PHILADELPHIA-Not_Center_City",
    TRUE ~ county
  )) %>%
  select(-"center_city")
# SET UP HOURLY AVERAGE TRIP DATA FOR EACH BUS STOP

dat_trip_count_hr <- dat %>%
  filter(mode %in% c("Bus", "Trolleybus", "Trolley")) %>%
  group_by(stop_id, mode, final_day_type) %>%
  summarise(trip_count = n(), 
            All_Routes = paste(unique(route_id), collapse = ", "),
            .groups = 'drop') %>%
  mutate(avg_trip_hr = round(trip_count/24)) %>%
  mutate(log_avg_trip_hr = round(log1p(avg_trip_hr), digits = 0)) %>%
  mutate(max_freq = ifelse(avg_trip_hr >= 12, "5 MAX",
                           ifelse (avg_trip_hr >= 6, "10 MAX",
                           ifelse (avg_trip_hr >= 4, "15 MAX", 
                           ifelse(avg_trip_hr >= 2, "30 MAX", "60 MAX")))))

dat_trip_count_hr <- left_join(dat_trip_count_hr, stops, by = "stop_id")

dat_trip_count_hr <- st_as_sf(dat_trip_count_hr, coords = c("stop_lon", "stop_lat"), crs = 4326, remove = FALSE)

# Assuming 'county' is the column with the county information
dat_trip_count_hr <- dat_trip_count_hr %>%
  mutate(category = if_else(county == "PHILADELPHIA", "urban", "suburban"))

# Simplify the max frequency into two categories
dat_trip_count_hr <- dat_trip_count_hr %>%
  mutate(simplified_freq = case_when(
    max_freq %in% c("5 MAX", "10 MAX", "15 MAX") ~ "15 minutes or less",
    TRUE ~ "More than 15 minutes"
  ))

# Remove rows where 'category' is NA
dat_trip_count_hr <- dat_trip_count_hr %>% filter(!is.na(category))

# sum(dat_trip_count_hr$trip_count) #1980505 <- Always make sure you retain the number of observation

Unraveling the Disparities in Bus Service Efficiency

The disparities in bus service efficiency between urban and suburban areas are starkly highlighted by frequency data. In suburban areas, the majority of bus stops suffer from infrequent services. This contrasts sharply with urban areas, where bus stops generally provide more frequent services. These differences underline significant inequities in transit accessibility, impacting daily commuters like Midge who rely heavily on these services.

In the following leaflet map, we illustrate these disparities. You’ll see that bus stops in suburban areas predominantly have longer waiting times, exceeding 15 minutes, whereas urban stops typically has waiting time under 15 minutes, demonstrating more frequent services. This visual representation emphasizes the urgent need for targeted improvements in suburban transit systems to bridge the gap and enhance overall service reliability and efficiency.

# SET UP AVERAGE TRIP DATA PER SERVICE PERIOD FOR EACH BUS STOP

dat_trip_count_prd <- dat %>%
  filter(mode %in% c("Bus", "Trolleybus", "Trolley")) %>%
  group_by(stop_id, peak_category, mode, final_day_type) %>%
  summarise(trip_count = n(), 
            All_Routes = paste(unique(route_id), collapse = ", "),
            .groups = 'drop') %>%
  mutate(
    hours = durations[peak_category],
    avg_trip_hr = round(trip_count / hours)
  ) %>%
  select(-hours) %>%
  mutate(log_avg_trip_hr = round(log1p(avg_trip_hr), digits = 0)) %>%
  mutate(max_freq = ifelse(avg_trip_hr >= 12, "5 MAX",
                           ifelse (avg_trip_hr >= 6, "10 MAX",
                           ifelse (avg_trip_hr >= 4, "15 MAX", 
                           ifelse(avg_trip_hr >= 2, "30 MAX", "60 MAX")))))

dat_trip_count_prd <- left_join(dat_trip_count_prd, stops, by = "stop_id")

dat_trip_count_prd <- st_as_sf(dat_trip_count_prd, coords = c("stop_lon", "stop_lat"), crs = 4326, remove = FALSE)

# sum(dat_trip_count_prd$trip_count)  #1980505 <- Always make sure you retain the number of observation

SEPTA_region_map <- st_transform(SEPTA_region_map, st_crs(dat_trip_count_hr))
# Define color palette for simplified frequency using the bus revolution colors
pal <- colorFactor(c("#A6123A", "#655BA6"), domain = c("15 minutes or less", "More than 15 minutes"))

# Create the leaflet map
m_avg_trip_hr <- leaflet() %>%
  addProviderTiles(providers$CartoDB.Positron) %>%
  addPolygons(data = SEPTA_region_map, color = "black", weight = 1, fill = FALSE) %>%
  addCircleMarkers(
    data = dat_trip_count_hr %>% filter(final_day_type == "Weekday" & !is.na(category)),
    group = ~category,  # Group data based on urban or suburban
    lng = ~stop_lon, 
    lat = ~stop_lat,
    color = ~pal(simplified_freq),  # Color based on simplified frequency
    radius = 1,
    opacity = 0.8,
    popup = ~paste0("<b>Stop ID:</b> ", stop_id, "<br>",
                    "<b>Stop Name:</b> ", stop_name, "<br>",
                    "<b>Avg Buses/Hr:</b> ", avg_trip_hr, "<br>",
                    "<b>Max Frequency:</b> ", simplified_freq, "<br>",
                    "<b>All Routes:</b> ", All_Routes)
  ) %>%
  addLayersControl(
    overlayGroups = c("urban", "suburban"),
    options = layersControlOptions(collapsed = FALSE)
  ) %>%
  addControl(html = "<div style='background-color: white; padding: 5px;'><strong>Source:</strong> SEPTA GTFS Data 2024</div>", position = "bottomleft")

# Display the map
m_avg_trip_hr

Midge’s daily challenge with inconsistent suburban bus service reflects broader transit inequities between urban and suburban settings. This disparity is exemplified by the operational inefficiencies of suburban routes, highlighted by data indicating these buses frequently fall within the lowest 15th percentile for service performance. This low percentile indicates prolonged wait times and unreliable schedules—factors contributing to higher operational costs and reduced reliability compared to more efficient urban counterparts.

Suburban buses, like the routes Midge uses, often suffer due to lower ridership densities and less optimized route planning, as reflected in the significant number of suburban routes like Routes 118, 129, and 90 underperforming in the 15th percentile. These routes’ inefficiencies starkly contrast with the robust transit systems in urban areas, underscoring a critical gap in transit equity and efficiency that demands innovative solutions.

route_evaluation <- read.csv("data/route_evaluation_report_2019.csv", sep = ";")

# Convert Cost.per.Passenger and Passengers.per.Revenue.Hour into proper numeric columns
route_evaluation$Cost.per.Passenger <- as.numeric(gsub("[$,]", "", route_evaluation$Cost.per.Passenger))
route_evaluation$Passengers.per.Revenue.Hour <- as.numeric(route_evaluation$Passengers.per.Revenue.Hour)

# Calculate 15th percentile for Passengers and 85th percentile for Cost (due to reversed axis)
passenger_15th <- quantile(route_evaluation$Passengers.per.Revenue.Hour, probs = 0.15, na.rm = TRUE)
cost_85th <- quantile(route_evaluation$Cost.per.Passenger, probs = 0.85, na.rm = TRUE)

# Define color palette for the types of buses
route_colors <- c("City Bus" = "#A6123A", "Suburban Bus" = "#655BA6")
pal <- colorFactor(route_colors, domain = unique(route_evaluation$Type))

# Create the ggplot
p <- ggplot(route_evaluation, aes(x = Passengers.per.Revenue.Hour, y = Cost.per.Passenger, color = Type, text = paste("Route:", Route, "<br>Passengers per Revenue Hour:", Passengers.per.Revenue.Hour, "<br>Cost per Passenger:", Cost.per.Passenger, "<br>Type:", Type))) +
  annotate("rect", xmin = 0, xmax = passenger_15th, ymin = max(route_evaluation$Cost.per.Passenger), ymax = cost_85th, fill = "lightcoral", alpha = 0.2) +
  geom_vline(xintercept = passenger_15th, linetype = "dashed", color = "grey") +
  geom_hline(yintercept = cost_85th, linetype = "dashed", color = "grey") +
  geom_point() +
  labs(title = "Performance of SEPTA City Bus and Suburban Bus",
       x = "Passengers per Revenue Hour",
       y = "Cost per Passenger",
       caption = "Source: SEPTA FY 2019 Report") +
  scale_color_manual(values = route_colors) +
  scale_y_reverse(breaks = seq(0, max(route_evaluation$Cost.per.Passenger, na.rm = TRUE), by = 1),
                  labels = dollar_format(prefix = "$", suffix = "", accuracy = 0.01)) +
  scale_x_continuous(breaks = seq(0, max(route_evaluation$Passengers.per.Revenue.Hour, na.rm = TRUE), by = 10)) +
  theme_minimal() +
  theme(legend.position = "none") +
  annotate("text", x = passenger_15th / 2, y = 6.5, label = "15th percentile", size = 3, color = "black", alpha = 0.5)

# Convert to plotly for an interactive plot with detailed hover information
p_plotly <- ggplotly(p, tooltip = "text")

# Display the interactive plot
p_plotly

Although microtransit has been proposed as an alternative to address these inefficiencies by offering more adaptable and potentially efficient services in lower-density areas, its effectiveness remains questionable. For example, AC Transit’s experiment in Oakland to replace fixed routes with microtransit resulted in a cost per passenger that more than doubled, highlighting the challenges of implementing such services effectively.9

This data illustrates that while microtransit is often touted as a modern solution for declining ridership, it generally does not perform as efficiently as traditional fixed-route services. The core efficiency of fixed-route transit comes from its ability to consolidate riders along a predictable path, minimizing deviations and ensuring consistent travel times. In contrast, microtransit’s on-demand nature can lead to significant inefficiencies, with routes constantly changing to accommodate individual pickup requests, leading to increased travel times and operational costs.

Given these challenges, it might be more prudent to explore other alternatives, such as deploying smaller, fixed-route minibusses during peak hours to enhance connectivity and manage crowding more effectively. This approach could leverage the lower operational costs of smaller vehicles while maintaining the structured efficiency of fixed-route transit, potentially offering a more sustainable solution to the suburban transit woes that Midge and countless others face daily.

Impact and Innovation: Enhancing Suburban Bus Services

While the raw data illuminates the service disparities, the true depth of this issue is best captured through the lived experiences of suburban commuters like Midge. Personal stories reveal the broader human impact: missed opportunities, prolonged workdays, and diminished family life due to infrequent bus services. This qualitative insight paints a vivid picture of the daily challenges and underscores the urgency for targeted improvements.

SEPTA’s ongoing “Bus Revolution” project aims to modernize and enhance bus services, promising updated routes and improved frequencies that haven’t been revised since the 1960s. While the initiative seeks to reduce headways to a maximum of 30 minutes even in the most remote suburban areas, it has faced delays and criticism, particularly concerning its potential to disproportionately impact low-income neighborhoods. This tension highlights the complex interplay between improving service efficiency and addressing community concerns of gentrification.

As we conclude our exploration of suburban bus transit disparities in Philadelphia, the compelling narratives of daily commuters, underpinned by robust SEPTA data, paint a clear picture of the challenges and the urgent need for systemic improvements. The “Bus Revolution” project, while a promising step toward enhancing bus frequencies and updating decades-old routes, also highlights the delicate balance required to improve service efficiency without exacerbating social inequities.

Embracing innovative solutions and fostering community engagement in transit planning are crucial. By committing to both technological upgrades and equitable service distribution, SEPTA can ensure that every commuter, regardless of where they live, has reliable and timely access to public transit. This not only improves individual daily experiences but also supports broader goals of economic mobility and sustainable urban development.

As stakeholders, we are called upon to support these initiatives, advocate for transparent and inclusive planning processes, and ensure that the voices of all commuters, especially those most affected like Midge, are heard and addressed in the pursuit of a truly connected and equitable transit system.

LS0tCnRpdGxlOiAiV2FpdGluZyBmb3IgQ2hhbmdlOiBUaGUgVXJnZW50IE5lZWQgZm9yIEVxdWl0YWJsZSBCdXMgU2VydmljZXMgaW4gU3VidXJiYW4gUGhpbGFkZWxwaGlhIgphdXRob3I6ICJSZWd5IFNlcHRpYW4iCmRhdGU6ICIyMDI0LTExLTMwIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiAiaGlkZSIKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBjYWNoZSA9IEZBTFNFKQoKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc2YpCmxpYnJhcnkodGlkeXRyYW5zaXQpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KGhtcykKbGlicmFyeSh0aWR5cikKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeSh3aykKbGlicmFyeShsZWFmbGV0KQpsaWJyYXJ5KGxlYWZsZXQuZXh0cmFzKQpsaWJyYXJ5KHZpcmlkaXMpCmxpYnJhcnkodmlyaWRpc0xpdGUpCmxpYnJhcnkoaHRtbHdpZGdldHMpCmxpYnJhcnkoaHRtbHRvb2xzKQpsaWJyYXJ5KGxlYWZsZXQuZXh0cmFzKQpsaWJyYXJ5KGZvcmNhdHMpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoc2hpbnkpCmxpYnJhcnkod2Vic2hvdDIpCmxpYnJhcnkobWFnaWNrKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShyZWFkcikKCiMgRGVmaW5lIHRoZSBjb2xvciBjb2RlcwpidXNfcmV2b2x1dGlvbl9jb2xvcnMgPC0gYygiI0E2MTIzQSIsICIjNjU1QkE2IiwgIiMyNkE2OTkiLCAiI0YyQUUyRSIsICIjRjJFNUQ1IikKCiMgQ3JlYXRlIGEgY3VzdG9tIHBhbGV0dGUgZnVuY3Rpb24KYnVzX3Jldm9sdXRpb25fcGFsZXR0ZSA8LSBmdW5jdGlvbihuKSB7CiAgY29sb3JSYW1wUGFsZXR0ZShidXNfcmV2b2x1dGlvbl9jb2xvcnMpKG4pCn0KCndvcmtkaXIgPC0gIn4vT25lRHJpdmUgLSBQZW5uTzM2NS8wM19VTklWRVJTSVRZX09GX1BFTk5TWUxWQU5JQS1NQ1BfMjAyNS8wNF9GQUxMXzI0LzAzX01VU0FfNjk1MV9Db21tdW5pY2F0aW9uX2luX1VyYmFuX1NwYXRpYWxfQW5hbHl0aWNzL01VU0EtNjMxMF9Bc3NpZ25tZW50LTIvTVVTQS02MzEwX0Fzc2lnbm1lbnQtMiIgIyBDaGFuZ2UgdGhlIGRpcmVjdG9yeQpzZXR3ZCh3b3JrZGlyKQpgYGAKCiMjIyBBIENvbW11dGVyJ3MgQ2hhbGxlbmdlIGluIFN1YnVyYmFuIFBoaWxhZGVscGhpYSAgCgpFdmVyeSBtb3JuaW5nLCBNaWRnZSwgYSBoZWFsdGhjYXJlIHdvcmtlciwgZW1iYXJrcyBvbiBoZXIgZGFpbHkgam91cm5leSBmcm9tIHRoZSBxdWlldCBzdHJlZXRzIG9mIFBvdHRzdG93blteMV0gaW4gTW9udGdvbWVyeSBDb3VudHkgdG8gdGhlIGJ1c3RsaW5nIGNvcnJpZG9ycyBvZiB0aGUgSG9zcGl0YWwgb2YgdGhlIFVuaXZlcnNpdHkgb2YgUGVubnN5bHZhbmlhIGluIFBoaWxhZGVscGhpYS4gSGVyIGNvbW11dGUgaXMgbW9yZSB0aGFuIGp1c3QgYSBwaHlzaWNhbCBqb3VybmV54oCUaXTigJlzIGEgZGFpbHkgb3JkZWFsLCB3cmVzdGxpbmcgd2l0aCB0aGUgaW5mcmVxdWVudCBhbmQgdW5yZWxpYWJsZSBidXMgc2VydmljZSB0aGF0IGNvbm5lY3RzIHRoZSBzdWJ1cmJhbiBzcHJhd2wgdG8gdGhlIHVyYmFuIGNvcmUuIE9uIGEgZ29vZCBkYXksIE1pZGdlIHdhaXRzIDMwIG1pbnV0ZXMgZm9yIEJ1cyA5Mzsgb24gYSBiYWQgZGF5LCB0aGUgd2FpdCBjYW4gZXhjZWVkIGFuIGhvdXIuIFNoZSBtdXN0IHRoZW4gdHJhbnNmZXIgdG8gdGhlIE5vcnJpc3Rvd24gSGlnaCBTcGVlZCBMaW5lLCBleHRlbmRpbmcgaGVyIHRvdGFsIG1vcm5pbmcgY29tbXV0ZSB0byBvdmVyIDIuNSBob3Vyc+KAlGZpdmUgdGltZXMgbG9uZ2VyIHRoYW4gUGhpbGFkZWxwaGlhJ3MgYXZlcmFnZSBjb21tdXRlIHRpbWUuW14yXSBUaGlzIGluY29uc2lzdGVuY3kgaXNuJ3QganVzdCBhIHBlcnNvbmFsIGluY29udmVuaWVuY2U7IGl0J3MgYSBzdGFyayByZWZsZWN0aW9uIG9mIHRoZSBicm9hZGVyIGlzc3VlcyBvZiB0cmFuc2l0IGluZXF1aXRpZXMgdGhhdCBwbGFndWUgbWFueSBpbiB0aGUgc3VidXJicywgd2hlcmUgYnVzZXMgYXJlIGZldyBhbmQgZmFyIGJldHdlZW4gZGVzcGl0ZSB0aGUgcHJlc3NpbmcgbmVlZC4KCk1pZGdlJ3Mgc3RvcnkgaXMgbm90IHVuaXF1ZSBpbiBHcmVhdGVyIFBoaWxhZGVscGhpYeKAlGEgcmVnaW9uIHdoZXJlIDU4LjIgcGVyY2VudCBvZiBwdWJsaWMgdHJhbnNpdCB1c2VycyBhcmUgd29tZW4gYW5kIDY2LjQgcGVyY2VudCBhcmUgcGVvcGxlIG9mIGNvbG9yLiBUaGVzZSBpbmRpdmlkdWFscyBwcmVkb21pbmFudGx5IHBvcHVsYXRlIGVzc2VudGlhbCBzZWN0b3JzIGxpa2UgaGVhbHRoY2FyZSwgZWR1Y2F0aW9uLCBhbmQgc29jaWFsIGFzc2lzdGFuY2Ugd2hpY2ggZW1wbG95cyAyNS42IHBlcmNlbnQgb2Ygc3VidXJiYW4gY291bnR5IHdvcmtlcnMgd2hvIGRlcGVuZCBvbiBwdWJsaWMgdHJhbnNwb3J0YXRpb24uIERlc3BpdGUgcGxheWluZyBjcml0aWNhbCByb2xlcyBpbiB0aGVpciBjb21tdW5pdGllcywgdGhlc2Ugd29ya2VycyBlYXJuIG1lZGlhbiBhbm51YWwgZWFybmluZ3MgYXBwcm94aW1hdGVseSAkNyw2NzMgYmVsb3cgdGhlIHJlZ2lvbmFsIGF2ZXJhZ2UuIFRoaXMgZWNvbm9taWMgZGlzcGFyaXR5IGlzIGV4YWNlcmJhdGVkIGJ5IHRoZSB0cmFuc2l0IGNoYWxsZW5nZXMgdGhleSBmYWNlLCB3aGVyZSB0aGUgZ2FwIGluIGFjY2Vzc2liaWxpdHkgYW5kIGZyZXF1ZW5jeSBvZiBzZXJ2aWNlIHdpZGVucyB0aGUgZGl2aWRlIGJldHdlZW4gZGlmZmVyZW50IHNvY2lvZWNvbm9taWMgZ3JvdXBzLiBBZGRpdGlvbmFsbHksIGEgc2lnbmlmaWNhbnQgcG9ydGlvbiBvZiB0aGUgd29ya2ZvcmNlLCBhYm91dCAzNSUsIGxpdmVzIGJlbG93IHRoZSBwb3ZlcnR5IGxpbmUsIGhlYXZpbHkgcmVseWluZyBvbiB0aGlzIHBhdGNod29yayBwdWJsaWMgdHJhbnNwb3J0IHN5c3RlbSB0aGF0IHN0cnVnZ2xlcyB0byBtZWV0IHRoZWlyIGRhaWx5IG5lZWRzLlteM10gCgpbXjFdOiBbV0hZWTogVHJhY2luZyBNb250Y2/igJlzIGRlY2FkZXMtbG9uZyBzaGlmdCBmcm9tIEdPUCBzdHJvbmdob2xkIHRvIGJvb24gZm9yIEJpZGVuXShodHRwczovL3doeXkub3JnL2FydGljbGVzL3RyYWNpbmctbW9udGNvcy1kZWNhZGVzLWxvbmctc2hpZnQtZnJvbS1nb3Atc3Ryb25naG9sZC10by1ib29uLWZvci1iaWRlbi8pClteMl06IFtUaGUgUGhpbGFkZWxwaGlhIElucXVpcmVyOiBQaGlsbHkgY29tbXV0ZXMgYXJlIGdldHRpbmcgc2xpZ2h0bHkgcXVpY2tlciwgYnV0IHRoZXnigJlyZSBhbW9uZyB0aGUgbG9uZ2VzdCBpbiB0aGUgVS5TLl0oaHR0cHM6Ly93d3cuaW5xdWlyZXIuY29tL3RyYW5zcG9ydGF0aW9uL3BoaWxhZGVscGhpYS1jb21tdXRlLXRpbWUtbG9uZ2VzdC10cmFuc2l0LTIwMjQxMDEwLmh0bWwjbG9hZGVkKQpbXjNdOiBbRWNvbm9teSBMZWFndWU6IEdyZWF0ZXIgUGhpbGFkZWxwaGlh4oCZcyBQdWJsaWMgVHJhbnNwb3J0YXRpb24gYW5kIENPVklELTE5IOKAkyBQQVJUIDJdKGh0dHBzOi8vd3d3LmVjb25vbXlsZWFndWUub3JnL3Jlc291cmNlcy9ncmVhdGVyLXBoaWxhZGVscGhpYXMtcHVibGljLXRyYW5zcG9ydGF0aW9uLWFuZC1jb3ZpZC0xOS1wYXJ0LTIjKQoKIyMjIFRoZSBJbXBvcnRhbmNlIG9mIFRyYW5zaXQgZm9yIFN1YnVyYmFuIENvbW11bml0aWVzICAKCk1pZGdl4oCZcyBkYWlseSBjb21tdXRlIHNoZWRzIGxpZ2h0IG9uIGEgbW9yZSBzaWduaWZpY2FudCBpc3N1ZTogdGhlIGNyaXRpY2FsIHJvbGUgb2YgcHVibGljIHRyYW5zcG9ydGF0aW9uIGluIHByb3ZpZGluZyBhY2Nlc3MgdG8gZXNzZW50aWFsIHNlcnZpY2VzIGFuZCBlY29ub21pYyBvcHBvcnR1bml0aWVzLCBlc3BlY2lhbGx5IGluIHN1YnVyYmFuIGNvbW11bml0aWVzLiBTdHVkaWVzIGhpZ2hsaWdodCBhIHJvYnVzdCBuZWdhdGl2ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHVuZW1wbG95bWVudCByYXRlcyBhbmQgcHJveGltaXR5IHRvIHRyYW5zaXQgYWNjZXNzLiBJbiBOZXcgWW9yayBDaXR5LCBuZWlnaGJvcmhvb2RzIHdpdGggc29tZSBidXQgbGltaXRlZCB0cmFuc2l0IGFjY2VzcyBleHBlcmllbmNlZCBhIHNpZ25pZmljYW50bHkgaGlnaGVyIHVuZW1wbG95bWVudCByYXRlICgxMi42JSkgY29tcGFyZWQgdG8gYXJlYXMgd2l0aCByb2J1c3QgdHJhbnNpdCBvcHRpb25zICg4LjElKS4gW140XSBUaGlzIGxhY2sgb2YgdHJhbnNpdCBhY2Nlc3MgbGltaXRzIHBoeXNpY2FsIGFuZCBlY29ub21pYyBtb2JpbGl0eSwgY29udHJpYnV0aW5nIHRvIGluY29tZSBpbmVxdWFsaXR5IGFuZCBoaWdoZXIgcHVibGljIGFzc2lzdGFuY2UgZGVwZW5kZW5jeS4KCk1vcmVvdmVyLCByZWxpYWJsZSBwdWJsaWMgdHJhbnNwb3J0YXRpb24gaXMgcGl2b3RhbCBmb3IgaGVhbHRoY2FyZSBhY2Nlc3MuIFRoZSBOYXRpb25hbCBIZWFsdGggSW50ZXJ2aWV3IFN1cnZleSAoMjAwMikgZXN0aW1hdGVkIHRoYXQgMy42IG1pbGxpb24gcGVvcGxlIG1pc3Mgbm9uLWVtZXJnZW5jeSBtZWRpY2FsIGFwcG9pbnRtZW50cyBhbm51YWxseSBkdWUgdG8gdHJhbnNwb3J0YXRpb24gaXNzdWVzLiBUaGlzIGlzc3VlIGRpc3Byb3BvcnRpb25hdGVseSBhZmZlY3RzIGNvbW11bml0aWVzIG9mIGNvbG9yLCB3aG8gcmVseSBtb3JlIGhlYXZpbHkgb24gcHVibGljIHRyYW5zcG9ydGF0aW9uIGNvbXBhcmVkIHRvIHdoaXRlIHBvcHVsYXRpb25zLiBbXjVdIE1pZGdl4oCZcyBjb21tdXRlIGlzIG5vdCBqdXN0IGEgbWF0dGVyIG9mIGNvbnZlbmllbmNlOyBpdOKAmXMgYWJvdXQgYWNjZXNzaW5nIGNydWNpYWwgaGVhbHRoY2FyZSBzZXJ2aWNlcyB0aGF0IG1hbmFnZSBjaHJvbmljIGNvbmRpdGlvbnMgYW5kIHByb3ZpZGUgbmVjZXNzYXJ5IHRyZWF0bWVudHMuCgpUcmFuc3BvcnRhdGlvbiBhbHNvIHBsYXlzIGEgZnVuZGFtZW50YWwgcm9sZSBpbiBlZHVjYXRpb25hbCBhY2Nlc3MuIFRoZSAiZ2VvZ3JhcGh5IG9mIG9wcG9ydHVuaXR5IiBzaWduaWZpY2FudGx5IHNoYXBlcyBlZHVjYXRpb25hbCBvdXRjb21lcyB0aHJvdWdoIGFjY2Vzc2libGUgdHJhbnNwb3J0YXRpb24sIGVuYWJsaW5nIGNoaWxkcmVuIGFuZCB5b3VuZyBwZW9wbGUgdG8gcmVhY2ggc2Nob29scyBhbmQgcGFydGljaXBhdGUgaW4gZXh0cmFjdXJyaWN1bGFyIGFjdGl2aXRpZXMuW142XSBBIHN0dWR5IGluIE1pbm5lYXBvbGlzIGZvdW5kIHRoYXQgaGlnaCBzY2hvb2wgc3R1ZGVudHMgd2l0aCBhY2Nlc3MgdG8gYW4gdW5saW1pdGVkIGJ1cyBhbmQgcmFpbCBwYXNzIGF0dGVuZGVkIHNjaG9vbCBtb3JlIHJlZ3VsYXJseSBhbmQgYWNoaWV2ZWQgaGlnaGVyIEdQQXMgYnkgMC4yMyB0aGFuIHN0dWRlbnRzIHdpdGhvdXQgYSBwYXNzLCBbXjddIGhpZ2hsaWdodGluZyB0aGUgaW1wb3J0YW5jZSBvZiByZWxpYWJsZSB0cmFuc2l0IGluIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQuCgpVc2luZyB0aGUgbGF0ZXN0IFNFUFRBIEdlbmVyYWwgVHJhbnNpdCBGZWVkIFNwZWNpZmljYXRpb24gKEdURlMpIGRhdGFbXjhdLCBpdCByZXZlYWxzIHRoYXQgYSBzdGFnZ2VyaW5nIDgwJSBvZiBTRVBUQSdzIHRyaXBzIGFyZSBtYWRlIGJ5IGJ1cywgc2hvd2Nhc2luZyB0aGUgY3JpdGljYWwgcm9sZSBvZiBidXMgdHJhbnNpdCBpbiBQaGlsYWRlbHBoaWHigJlzIHRyYW5zcG9ydGF0aW9uIG5ldHdvcmsuIFRoaXMgc3RhdGlzdGljIHVuZGVybGluZXMgdGhlIGhlYXZ5IHJlbGlhbmNlIG9uIGJ1c2VzIGFjcm9zcyB0aGUgY2l0eSwgbm90IGp1c3QgaW4gc3VidXJiYW4gYXJlYXMuIAoKW140XTogW0thdWZtYW4gYW5kIGNvbGxlYWd1ZXMgMjAxNV0oaHR0cHM6Ly93YWduZXIubnl1LmVkdS9maWxlcy9mYWN1bHR5L3B1YmxpY2F0aW9ucy9Kb2JBY2Nlc3NOb3YyMDE1LnBkZikKW141XTogW1dhbGxhY2UgZXQgYWwuIDIwMTVdKGh0dHBzOi8vam91cm5hbHMuc2FnZXB1Yi5jb20vZG9pL2Ficy8xMC4xMTc3LzAzNjExOTgxMDUxOTI0MDAxMTApClteNl06IFtWaW5jZW50IGV0IGFsLiAyMDE0XShodHRwczovL2VyaWMuZWQuZ292Lz9pZD1FRDU1ODU0MikKW143XTogW0ZhbiBhbmQgRGFzIDIwMTVdKGh0dHBzOi8vY29uc2VydmFuY3kudW1uLmVkdS9pdGVtcy81ZDk5ODk2OC1hYWZlLTRiZjAtOTJkOC1lNWRhNTczMmY0ZjcpClteOF06IFtTRVBUQSBHVEZTXShodHRwczovL3d3dzMuc2VwdGEub3JnL2RldmVsb3Blci9ndGZzX3B1YmxpYy56aXApCgoKYGBge3IgaW1wb3J0IGd0ZnMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUUsIHJlc3VsdHMgPSAnaGlkZSd9CiMgSW1wb3J0IEdURlMgZGF0YQpzdG9wcyA8LSByZWFkLmNzdigiZGF0YS9nb29nbGVfYnVzL3N0b3BzLnR4dCIsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICIsIikKc3RvcF90aW1lcyA8LSByZWFkLmNzdigiZGF0YS9nb29nbGVfYnVzL3N0b3BfdGltZXMudHh0IiwgaGVhZGVyID0gVFJVRSwgc2VwID0gIiwiKQp0cmlwcyA8LSByZWFkLmNzdigiZGF0YS9nb29nbGVfYnVzL3RyaXBzLnR4dCIsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICIsIikKc2hhcGVzIDwtIHJlYWQuY3N2KCJkYXRhL2dvb2dsZV9idXMvc2hhcGVzLnR4dCIsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICIsIikKcm91dGVzIDwtIHJlYWQuY3N2KCJkYXRhL2dvb2dsZV9idXMvcm91dGVzLnR4dCIsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICIsIikKY2FsZW5kYXIgPC0gcmVhZC5jc3YoImRhdGEvZ29vZ2xlX2J1cy9jYWxlbmRhci50eHQiLCBoZWFkZXIgPSBUUlVFLCBzZXAgPSAiLCIpCmNhbGVuZGFyX2RhdGVzIDwtIHJlYWQuY3N2KCJkYXRhL2dvb2dsZV9idXMvY2FsZW5kYXJfZGF0ZXMudHh0IiwgaGVhZGVyID0gVFJVRSwgc2VwID0gIiwiKQoKIyBJbXBvcnQgU3dpZnRseSBkYXRhCnN3aWZ0bHkgPC0gc3RfcmVhZCgiZGF0YS9Td2lmdGx5U2hhcGVzL2dlb0pTT05zL1NFUFRBU3VyZmFjZV9IaWdoUmVzU3BlZWRfdjIuanNvbiIpCgpgYGAKCmBgYHtyIHRvdGFsIHRyaXAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUV9CiMgSm9pbiBzdG9wX3RpbWVzIGFuZCB0cmlwcywgZnJvbSBub3cgb24gZGF0IHdpbGwgYmUgb3VyIG1haW4gZGF0YSBzZXQKZGF0IDwtIGxlZnRfam9pbihzdG9wX3RpbWVzLCB0cmlwcywgYnkgPSAidHJpcF9pZCIpCgojIGpvaW4gZGF0IGFuZCByb3V0ZXMKZGF0IDwtIGxlZnRfam9pbihkYXQsIHJvdXRlcywgYnkgPSAicm91dGVfaWQiKQoKI2RldGVybWluZSByb3V0ZV90eXBlCmRhdCA8LSBkYXQgJT4lCiAgbXV0YXRlKG1vZGUgPSBpZl9lbHNlKHJvdXRlX3R5cGUgPT0gMCwgIlRyb2xsZXkiLCBpZmVsc2Uocm91dGVfdHlwZSA9PSAxLCAiTWV0cm8iLCBpZmVsc2Uocm91dGVfdHlwZSA9PSAzLCAiQnVzIiwgIlRyb2xsZXlidXMiKSkpKQoKIyBNb2RlIHNoYXJlIChub3QgcmlkZXJzaGlwKQpkYXRfdHJpcF9ieV9tb2RlIDwtIGRhdCAlPiUKICBncm91cF9ieShtb2RlKSAlPiUKICBzdW1tYXJpc2UobW9kZV9jb3VudCA9IG4oKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgbXV0YXRlKHRvdGFsX2NvdW50ID0gc3VtKG1vZGVfY291bnQpLAogICAgICAgICBtb2RlX3NoYXJlID0gcm91bmQobW9kZV9jb3VudC9zdW0obW9kZV9jb3VudCkqMTAwLCBkaWdpdHMgPSAyKSkgJT4lCiAgdW5ncm91cCgpIAogIAojICMgUGxvdCBtb2RlIHNoYXJlIHVzaW5nIGdncGxvdDIgYW5kIHRoZSBjdXN0b20gcGFsZXR0ZQpnZ3Bsb3QoZGF0X3RyaXBfYnlfbW9kZSwgYWVzKHggPSBtb2RlLCB5ID0gbW9kZV9zaGFyZSwgZmlsbCA9IG1vZGUpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMC43NSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGJ1c19yZXZvbHV0aW9uX3BhbGV0dGUobGVuZ3RoKHVuaXF1ZShkYXRfdHJpcF9ieV9tb2RlJG1vZGUpKSkpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKG1vZGVfc2hhcmUsICIlICgiLCBtb2RlX2NvdW50LCAiIHRyaXBzKSIpKSwKICAgICAgICAgICAgdmp1c3QgPSAtMC41LCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAyLjUpICsKICBsYWJzKHRpdGxlID0gIk1vZGUgU2hhcmUgYnkgVHJhbnNpdCBUeXBlIiwKICAgICAgIHggPSAiTW9kZSIsCiAgICAgICB5ID0gIk1vZGUgU2hhcmUgKCUpIiwKICAgICAgIGZpbGwgPSAiTW9kZSIsCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogU0VQVEEgR1RGUyBEYXRhIDIwMjQiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQojIAojICMgdG90YWwgdHJpcCBidXMgJiB0cm9sbGV5IGJ1cyAxLjk4MC41MDUsIHRvdGFsIG9ic2VydmF0aW9ucyAyLjAyNi42NzcKIyAKIyBnZ3Bsb3QoKSArCiMgICAjIEFkZCBzZXJ2aWNlIHBlcmlvZCBiYWNrZ3JvdW5kIHJlY3RhbmdsZXMgd2l0aCByZWR1Y2VkIGFscGhhIGZvciBzdWJ0bGV0eQojICAgZ2VvbV9yZWN0KGRhdGEgPSBzZXJ2aWNlX3BlcmlvZHMsIGFlcyh4bWluID0gc3RhcnRfaG91ciwgeG1heCA9IGVuZF9ob3VyLCB5bWluID0gMCwgeW1heCA9IG1heChob3VybHlfdHJpcHMkbnVtYmVyX29mX3RyaXBzKSwgZmlsbCA9IHBlYWtfY2F0ZWdvcnkpLCBhbHBoYSA9IDAuMikgKwojICAgIyBBZGQgdGhlIGxpbmUgcGxvdCBmb3Igd2Vla2RheSB0cmlwcyB3aXRoIGFkanVzdGVkIHBvaW50IHNpemVzCiMgICBnZW9tX2xpbmUoZGF0YSA9IGhvdXJseV90cmlwcyAlPiUgZmlsdGVyKGZpbmFsX2RheV90eXBlID09ICJXZWVrZGF5IiksIGFlcyh4ID0gaG91ciwgeSA9IG51bWJlcl9vZl90cmlwcyksIGNvbG9yID0gIiNGMkFFMkUiLCBzaXplID0gMSkgKwojICAgZ2VvbV9wb2ludChkYXRhID0gaG91cmx5X3RyaXBzICU+JSBmaWx0ZXIoZmluYWxfZGF5X3R5cGUgPT0gIldlZWtkYXkiKSwgYWVzKHggPSBob3VyLCB5ID0gbnVtYmVyX29mX3RyaXBzKSwgY29sb3IgPSAiIzI2QTY5OSIsIHNpemUgPSAzKSArCiMgICAjIEFkZCB0aGUgbGluZSBwbG90IGZvciB3ZWVrZW5kIHRyaXBzIHdpdGggYSBuZXcgY29sb3IgZm9yIGJldHRlciBkaWZmZXJlbnRpYXRpb24KIyAgIGdlb21fbGluZShkYXRhID0gaG91cmx5X3RyaXBzICU+JSBmaWx0ZXIoZmluYWxfZGF5X3R5cGUgPT0gIldlZWtlbmQiKSwgYWVzKHggPSBob3VyLCB5ID0gbnVtYmVyX29mX3RyaXBzKSwgY29sb3IgPSAiIzAwNzJCMiIsIHNpemUgPSAxKSArCiMgICBnZW9tX3BvaW50KGRhdGEgPSBob3VybHlfdHJpcHMgJT4lIGZpbHRlcihmaW5hbF9kYXlfdHlwZSA9PSAiV2Vla2VuZCIpLCBhZXMoeCA9IGhvdXIsIHkgPSBudW1iZXJfb2ZfdHJpcHMpLCBjb2xvciA9ICIjRDU1RTAwIiwgc2l6ZSA9IDMpICsKIyAgICMgRGVmaW5lIHNjYWxlcyBhbmQgbGFiZWxzIHdpdGggYXBwcm9wcmlhdGUgYWRqdXN0bWVudHMKIyAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAwOjIzKSArCiMgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkgKwojICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gc2VydmljZV9wZXJpb2RfY29sb3JzKSArCiMgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiV2Vla2RheSIgPSAiI0YyQUUyRSIsICJXZWVrZW5kIiA9ICIjMDA3MkIyIikpICsKIyAgIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIFRyaXBzIGJ5IEhvdXIgd2l0aCBTZXJ2aWNlIFBlcmlvZHMiLAojICAgICAgICB4ID0gIkhvdXIgb2YgRGF5IiwKIyAgICAgICAgeSA9ICJOdW1iZXIgb2YgVHJpcHMiLAojICAgICAgICBmaWxsID0gIlNlcnZpY2UgUGVyaW9kIiwKIyAgICAgICAgY29sb3IgPSAiRGF5IFR5cGUiKSArCiMgICB0aGVtZV9taW5pbWFsKCkgKwojICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiMgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgpgYGB7ciBwZWFrIHRpbWUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUUsIHJlc3VsdHMgPSAnaGlkZSd9CiMgQ1JFQVRFIExJTkUgR1JBUEggT0YgVFJJUFMgQlkgU0VSVklDRSBQRVJJT0RTCgojIEZ1bmN0aW9uIHRvIG5vcm1hbGl6ZSB0aW1lcyBncmVhdGVyIHRoYW4gMjQ6MDA6MDAuIEltcG9ydGFudCBzdGVwOiBjaGVjayB0aGUgc3RvcF90aW1lcyRhcnJpdmFsX3RpbWUgYW5kIGRlcGFydHVyZV90aW1lIHZhbHVlcyBpZiBpdCdzIGdyZWF0ZXIgdGhhbiAyNDowMCAKbm9ybWFsaXplX3RpbWUgPC0gZnVuY3Rpb24odGltZV9zdHIpIHsKICB0aW1lX3BhcnRzIDwtIHN0cnNwbGl0KHRpbWVfc3RyLCAiOiIpW1sxXV0KICBob3VycyA8LSBhcy5udW1lcmljKHRpbWVfcGFydHNbMV0pCiAgbWludXRlcyA8LSBhcy5udW1lcmljKHRpbWVfcGFydHNbMl0pCiAgc2Vjb25kcyA8LSBhcy5udW1lcmljKHRpbWVfcGFydHNbM10pCiAgCiAgaWYgKGhvdXJzID49IDI0KSB7CiAgICBob3VycyA8LSBob3VycyAtIDI0CiAgICB0aW1lX3N0ciA8LSBzcHJpbnRmKCIlMDJkOiUwMmQ6JTAyZCIsIGhvdXJzLCBtaW51dGVzLCBzZWNvbmRzKQogIH0KICAKICByZXR1cm4odGltZV9zdHIpCn0KCiNpZGVudGlmeSBwZWFrX3BtIGNhdGVnb3J5IApkYXQgPC0gZGF0ICU+JQogIG11dGF0ZShkZXBhcnR1cmVfdGltZSA9IHNhcHBseShkZXBhcnR1cmVfdGltZSwgbm9ybWFsaXplX3RpbWUpLCAjIGRlcGFydHVyZV90aW1lJ3Mgbm9ybWFsaXplZAogICAgICAgICBkZXBhcnR1cmVfdGltZSA9IGx1YnJpZGF0ZTo6aG1zKGRlcGFydHVyZV90aW1lKSwKICAgICAgICAgaG91ciA9IGhvdXIoZGVwYXJ0dXJlX3RpbWUpLCAgIyBFeHRyYWN0IGhvdXIgY29tcG9uZW50IGZvciBlYXNpZXIgY29uZGl0aW9uIGNoZWNraW5nCiAgICAgICAgIHBlYWtfY2F0ZWdvcnkgPSBpZl9lbHNlKGhvdXIgPj0gNCAmIGhvdXIgPCA2LCAiRWFybHkgTW9ybmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UoaG91ciA+PSA2ICYgaG91ciA8IDksICJBTSBQZWFrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKGhvdXIgPj0gOSAmIGhvdXIgPCAxNSwgIk1pZCBEYXkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShob3VyID49IDE1ICYgaG91ciA8IDE4LCAiUE0gUGVhayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UoaG91ciA+PSAxOCAmIGhvdXIgPCAyMiwgIkV2ZW5pbmciLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoaG91ciA+PSAyMiAmIGhvdXIgPCAyNCwgIkxhdGUgTmlnaHQiLCAiT3dsIikpKSkpKSkgCgojICMgQ2hlY2sgaWYgdGhlcmUgYXJlIGFueSBOQSB2YWx1ZXMgaW4gdGhlICdkZXBhcnR1cmVfdGltZScgY29sdW1uCiMgc3VtbWFyaXNlKGRhdCwKIyAgICAgbmFfY291bnQgPSBzdW0oaXMubmEoZGVwYXJ0dXJlX3RpbWUpKSwgI0NvdW50IE5BIHZhbHVlcwojICAgICB0b3RhbF9yb3dzID0gbigpLCAgIyBUb3RhbCBudW1iZXIgb2Ygcm93cyBmb3IgY29udGV4dAojICAgICBwZXJjZW50YWdlX25hID0gbmFfY291bnQgLyB0b3RhbF9yb3dzICogMTAwICAjIFBlcmNlbnRhZ2Ugb2YgTkEgdmFsdWVzCiMgICApCgpkdXJhdGlvbnMgPC0gYygiT3dsIiA9IDQsICJFYXJseSBNb3JuaW5nIiA9IDIsICJBTSBQZWFrIiA9IDMsICJNaWQgRGF5IiA9IDYsICJQTSBQZWFrIiA9IDMsICJFdmVuaW5nIiA9IDQsICJMYXRlIE5pZ2h0IiA9IDIpCgpkYXRfc2VydmljZV9wZXJpb2QgPC0gZGF0ICU+JQogIGZpbHRlcihtb2RlICVpbiUgYygiQnVzIiwgIlRyb2xsZXlidXMiLCAiVHJvbGxleSIpKSAlPiUKICBncm91cF9ieShwZWFrX2NhdGVnb3J5KSU+JQogIHN1bW1hcmlzZShwZWFrX2NvdW50ID0gbigpLCAuZ3JvdXBzID0gJ2Ryb3AnKSAlPiUKICBtdXRhdGUodG90YWxfY291bnQgPSBzdW0ocGVha19jb3VudCksCiAgICAgICAgIHBlYWtfc2hhcmUgPSByb3VuZChwZWFrX2NvdW50L3N1bShwZWFrX2NvdW50KSoxMDAsIGRpZ2l0cyA9IDIpKSAlPiUKICBhcnJhbmdlKGZhY3RvcihwZWFrX2NhdGVnb3J5LCBsZXZlbHMgPSBjKCJPd2wiLCAiRWFybHkgTW9ybmluZyIsICJBTSBQZWFrIiwgIk1pZCBEYXkiLCAiUE0gUGVhayIsICJFdmVuaW5nIiwgIkxhdGUgTmlnaHQiKSkpICU+JQogIHVuZ3JvdXAoKQoKIyBDcmVhdGUgYSBkYXRhIGZyYW1lIGZvciBzZXJ2aWNlIHBlcmlvZHMKc2VydmljZV9wZXJpb2RzIDwtIGRhdGEuZnJhbWUoCiAgcGVha19jYXRlZ29yeSA9IGMoIk93bCIsICJFYXJseSBNb3JuaW5nIiwgIkFNIFBlYWsiLCAiTWlkIERheSIsICJQTSBQZWFrIiwgIkV2ZW5pbmciLCAiTGF0ZSBOaWdodCIpLAogIHN0YXJ0X2hvdXIgPSBjKDAsIDQsIDYsIDksIDE1LCAxOCwgMjIpLAogIGVuZF9ob3VyID0gYyg0LCA2LCA5LCAxNSwgMTgsIDIyLCAyNCkKKQoKIyBDUkVBVEUgQkFSIENIQVJUIE9GIFRSSVBTIEJZIFNFUlZJQ0UgVFlQRVMKCiMgRW5zdXJlICdjYWxlbmRhcicgaGFzICdkYXlfdHlwZScgZGVmaW5lZApjYWxlbmRhciA8LSBjYWxlbmRhciAlPiUKICBtdXRhdGUoCiAgICBkYXlfdHlwZSA9IGNhc2Vfd2hlbigKICAgICAgbW9uZGF5ID09IDEgJiB0dWVzZGF5ID09IDEgJiB3ZWRuZXNkYXkgPT0gMSAmIHRodXJzZGF5ID09IDEgJiBmcmlkYXkgPT0gMSAmIHNhdHVyZGF5ID09IDAgJiBzdW5kYXkgPT0gMCB+ICJXZWVrZGF5IiwKICAgICAgKHNhdHVyZGF5ID09IDEgfCBzdW5kYXkgPT0gMSkgfiAiV2Vla2VuZCIsCiAgICAgIFRSVUUgfiAiaXJyZWd1bGFyIgogICAgKQogICkKCiMgQ2FsZW5kYXJfZGF0ZXMgaW5jbHVkZXMgJ3NlcnZpY2VfaWQnLCAnZGF0ZScsIGFuZCAnZXhjZXB0aW9uX3R5cGUnCiMgRW5zdXJlICdjYWxlbmRhcl9kYXRlcycgaGFzICdkYXlfdHlwZScgZGVmaW5lZCBiYXNlZCBvbiB0aGUgZGF0ZQpjYWxlbmRhcl9kYXRlcyA8LSBjYWxlbmRhcl9kYXRlcyAlPiUKICBmaWx0ZXIoZXhjZXB0aW9uX3R5cGUgPT0gMSkgJT4lICN3ZSBvbmx5IG5lZWQgZXhjZXB0aW9uX3R5cGUgPT0gMSwgdGhvc2UgYWRkZWQgdG8gdGhlIHNlcnZpY2UKICBtdXRhdGUoCiAgICBkYXRlID0geW1kKGRhdGUpLCAgIyBDb252ZXJ0IGRhdGUgZm9ybWF0IGlmIG5lY2Vzc2FyeQogICAgZGF5X29mX3dlZWsgPSB3ZGF5KGRhdGUsIGxhYmVsID0gVFJVRSwgd2Vla19zdGFydCA9IDEpLAogICAgZGF5X3R5cGUgPSBjYXNlX3doZW4oCiAgICAgIGRheV9vZl93ZWVrICVpbiUgYygiTW9uIiwgIlR1ZSIsICJXZWQiLCAiVGh1IiwgIkZyaSIpIH4gIldlZWtkYXkiLCAgIyBNb25kYXkgdG8gRnJpZGF5CiAgICAgIFRSVUUgfiAiV2Vla2VuZCIgICMgU2F0dXJkYXkgYW5kIFN1bmRheQogICAgKQogICkKCiMgSm9pbiBjYWxlbmRhcl9kYXRlcyB3aXRoIGNhbGVuZGFyCmNhbGVuZGFyX2pvaW5lZCA8LSBjYWxlbmRhcl9kYXRlcyAlPiUKICBmdWxsX2pvaW4oY2FsZW5kYXIsIGJ5ID0gInNlcnZpY2VfaWQiLCBzdWZmaXggPSBjKCIuZGF0ZXMiLCAiLmNhbCIpKSAlPiUKICBtdXRhdGUoCiAgICBmaW5hbF9kYXlfdHlwZSA9IGNhc2Vfd2hlbigKICAgICAgIyBVc2UgY2FsZW5kYXJfZGF0ZXMnIGRheV90eXBlIGlmIGV4Y2VwdGlvbl90eXBlIGluZGljYXRlcyBhZGRlZCBzZXJ2aWNlCiAgICAgIGV4Y2VwdGlvbl90eXBlID09IDEgJiBkYXlfdHlwZS5kYXRlcyA9PSAiV2Vla2RheSIgfiAiV2Vla2RheSIsCiAgICAgIGV4Y2VwdGlvbl90eXBlID09IDEgJiBkYXlfdHlwZS5kYXRlcyA9PSAiV2Vla2VuZCIgfiAiV2Vla2VuZCIsCiAgICAgICMgRGVmYXVsdCB0byBjYWxlbmRhcidzIGRheV90eXBlIHdoZXJlIHRoZXJlJ3Mgbm8gc3BlY2lmaWMgZXhjZXB0aW9uIG5vdGVkCiAgICAgIFRSVUUgfiBkYXlfdHlwZS5jYWwKICAgICkKICApICU+JQogIHNlbGVjdChzZXJ2aWNlX2lkLCBmaW5hbF9kYXlfdHlwZSkgJT4lCiAgZ3JvdXBfYnkoc2VydmljZV9pZCwgZmluYWxfZGF5X3R5cGUpICU+JQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgYXJyYW5nZShzZXJ2aWNlX2lkLCBkZXNjKGNvdW50KSkgJT4lCiAgZGlzdGluY3Qoc2VydmljZV9pZCwgLmtlZXBfYWxsID0gVFJVRSkgJT4lICMgTWFrZSBzdXJlIG5vIGRvdWJsZSBkYXkgdHlwZXMgZm9yIHNlcnZpY2UgSUQKICBzZWxlY3QoLWNvdW50KQogIApkYXQgPC0gZGF0ICU+JQogIGxlZnRfam9pbihjYWxlbmRhcl9qb2luZWQsIGJ5ID0gInNlcnZpY2VfaWQiKQoKYGBgCgpgYGB7ciBjYWxlbmRhciwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KZGF0X3NlcnZpY2VfdHlwZSA8LSBkYXQgJT4lCiAgZmlsdGVyKG1vZGUgJWluJSBjKCJCdXMiLCAiVHJvbGxleWJ1cyIsICJUcm9sbGV5IikpICU+JQogIGdyb3VwX2J5KGZpbmFsX2RheV90eXBlKSU+JQogIHN1bW1hcmlzZShkYXlfdHlwZV9jb3VudCA9IG4oKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgbXV0YXRlKHRvdGFsX2NvdW50ID0gc3VtKGRheV90eXBlX2NvdW50KSwKICAgICAgICAgcGVha19zaGFyZSA9IHJvdW5kKGRheV90eXBlX2NvdW50L3N1bShkYXlfdHlwZV9jb3VudCkqMTAwLCBkaWdpdHMgPSAyKSkgJT4lCiAgYXJyYW5nZShmYWN0b3IoZmluYWxfZGF5X3R5cGUsIGxldmVscyA9IGMoIldlZWtkYXkiLCAiV2Vla2VuZCIpKSkgJT4lCiAgdW5ncm91cCgpCgojIFN1bW1hcml6ZSBkYXRhIHRvIGdldCB0aGUgbnVtYmVyIG9mIHRyaXBzIHBlciBob3VyCmhvdXJseV90cmlwcyA8LSBkYXQgJT4lCiAgZmlsdGVyKG1vZGUgJWluJSBjKCJCdXMiLCAiVHJvbGxleWJ1cyIsICJUcm9sbGV5IikpICU+JQogIGdyb3VwX2J5KGhvdXIsIGZpbmFsX2RheV90eXBlKSAlPiUKICBzdW1tYXJpc2UobnVtYmVyX29mX3RyaXBzID0gbigpKQoKIyBEZWZpbmUgYSBjdXN0b20gcGFsZXR0ZSBmb3IgdGhlIHNlcnZpY2UgcGVyaW9kcwpzZXJ2aWNlX3BlcmlvZF9jb2xvcnMgPC0gYygKICAiT3dsIiA9ICIjRTVFNUU1IiwKICAiRWFybHkgTW9ybmluZyIgPSAiI0M1RTBCNCIsCiAgIkFNIFBlYWsiID0gIiNBOUQwOEUiLAogICJNaWQgRGF5IiA9ICIjRkZEOTY2IiwKICAiUE0gUGVhayIgPSAiI0Y0QjA4NCIsCiAgIkV2ZW5pbmciID0gIiNENUE2QkQiLAogICJMYXRlIE5pZ2h0IiA9ICIjQTRDMkY0IgopCgojICMgUGxvdCB0aGUgY29tYmluZWQgZ3JhcGgKIyBnZ3Bsb3QoKSArCiMgICAjIEFkZCBzZXJ2aWNlIHBlcmlvZCBiYWNrZ3JvdW5kIHJlY3RhbmdsZXMKIyAgIGdlb21fcmVjdChkYXRhID0gc2VydmljZV9wZXJpb2RzLCBhZXMoeG1pbiA9IHN0YXJ0X2hvdXIsIHhtYXggPSBlbmRfaG91ciwgeW1pbiA9IDAsIHltYXggPSBtYXgoaG91cmx5X3RyaXBzJG51bWJlcl9vZl90cmlwcyksIGZpbGwgPSBwZWFrX2NhdGVnb3J5KSwgYWxwaGEgPSAwLjMpICsKIyAgICMgQWRkIHRoZSBsaW5lIHBsb3QgZm9yIHdlZWtkYXkgdHJpcHMKIyAgIGdlb21fbGluZShkYXRhID0gaG91cmx5X3RyaXBzICU+JSBmaWx0ZXIoZmluYWxfZGF5X3R5cGUgPT0gIldlZWtkYXkiKSwgYWVzKHggPSBob3VyLCB5ID0gbnVtYmVyX29mX3RyaXBzKSwgY29sb3IgPSAiI0YyQUUyRSIsIHNpemUgPSAxKSArCiMgICBnZW9tX3BvaW50KGRhdGEgPSBob3VybHlfdHJpcHMgJT4lIGZpbHRlcihmaW5hbF9kYXlfdHlwZSA9PSAiV2Vla2RheSIpLCBhZXMoeCA9IGhvdXIsIHkgPSBudW1iZXJfb2ZfdHJpcHMpLCBjb2xvciA9ICIjMjZBNjk5Iiwgc2l6ZSA9IDIpICsKIyAgICMgQWRkIHRoZSBsaW5lIHBsb3QgZm9yIHdlZWtlbmQgdHJpcHMKIyAgIGdlb21fbGluZShkYXRhID0gaG91cmx5X3RyaXBzICU+JSBmaWx0ZXIoZmluYWxfZGF5X3R5cGUgPT0gIldlZWtlbmQiKSwgYWVzKHggPSBob3VyLCB5ID0gbnVtYmVyX29mX3RyaXBzKSwgY29sb3IgPSAiI0E2MTIzQSIsIHNpemUgPSAxKSArCiMgICBnZW9tX3BvaW50KGRhdGEgPSBob3VybHlfdHJpcHMgJT4lIGZpbHRlcihmaW5hbF9kYXlfdHlwZSA9PSAiV2Vla2VuZCIpLCBhZXMoeCA9IGhvdXIsIHkgPSBudW1iZXJfb2ZfdHJpcHMpLCBjb2xvciA9ICIjMjZBNjk5Iiwgc2l6ZSA9IDIpICsKIyAgICMgRGVmaW5lIHNjYWxlcyBhbmQgbGFiZWxzCiMgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMDoyMykgKwojICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hKSArCiMgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBzZXJ2aWNlX3BlcmlvZF9jb2xvcnMpICsKIyAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJXZWVrZGF5IiA9ICIjRjJBRTJFIiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV2Vla2VuZCIgPSAiI0E2MTIzQSIpKSArCiMgICBsYWJzKHRpdGxlID0gIk51bWJlciBvZiBUcmlwcyBieSBIb3VyIHdpdGggU2VydmljZSBQZXJpb2RzIiwKIyAgICAgICAgeCA9ICJIb3VyIG9mIERheSIsCiMgICAgICAgIHkgPSAiTnVtYmVyIG9mIFRyaXBzIiwKIyAgICAgICAgZmlsbCA9ICJTZXJ2aWNlIFBlcmlvZCIsCiMgICAgICAgIGNvbG9yID0gIkRheSBUeXBlIikgKwojICAgdGhlbWVfbWluaW1hbCgpICsKIyAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAojICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCiAgCmBgYAoKCmBgYHtyIHNldCB1cCBzdG9wcyBjYXRlZ29yeSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgY2FjaGU9VFJVRSwgcmVzdWx0cyA9ICdoaWRlJ30KIyBTRVQgVVAgU1RPUFMgQ0FURUdPUlkuIFRoaXMgc3RlcCBpcyBjcnVjaWFsIGFzIHdlJ2xsIHVzZSBzdG9wcyBpbmZvcm1hdGlvbiBhbmQgam9pbiB0aGVtIGZvciBlYWNoIGtpbmQgb2YgbWFwcyAKCiMgQ29udmVydCBzdG9wcyBkYXRhIHRvIHNmIG9iamVjdApzdG9wcyA8LSBzdG9wcyAlPiUKICBzdF9hc19zZihjb29yZHMgPSBjKCJzdG9wX2xvbiIsICJzdG9wX2xhdCIpLCBjcnMgPSA0MzI2LCByZW1vdmUgPSBGQUxTRSkKCiMgTG9hZCBQQSBhbmQgU0VQVEEgcmVnaW9uIG1hcCBmb3IgYmFzZSBtYXAKUEEgPC0gc3RfcmVhZCgiZGF0YS9QYUNvdW50eTIwMjRfMDUuZ2VvanNvbiIpClNFUFRBX3JlZ2lvbl9tYXAgPC0gUEFbUEEkQ09VTlRZX05BTSAlaW4lIGMoIk1PTlRHT01FUlkiLCAiQlVDS1MiLCAiUEhJTEFERUxQSElBIiwgIkRFTEFXQVJFIiwgIkNIRVNURVIiKSwgXSAlPiUKICBzZWxlY3QoUEFfQ1RZX0NPRCwgQ09VTlRZX05BTSwgRklQU19DT1VOVCkKCiMgTG9hZCBDZW50ZXIgQ2l0eSBib3VuZGFyeQpjZW50ZXJfY2l0eSA8LSBzdF9yZWFkKCJkYXRhLzIwMjQwNzA4X0NlbnRlckNpdHkvQ2VudGVyQ2l0eS5zaHAiKQoKIyBFbnN1cmUgYWxsIGRhdGFzZXRzIGFyZSBpbiB0aGUgc2FtZSBDUlMKU0VQVEFfcmVnaW9uX21hcCA8LSBzdF90cmFuc2Zvcm0oU0VQVEFfcmVnaW9uX21hcCwgY3JzID0gc3RfY3JzKHN0b3BzKSkKY2VudGVyX2NpdHkgPC0gc3RfdHJhbnNmb3JtKGNlbnRlcl9jaXR5LCBjcnMgPSBzdF9jcnMoc3RvcHMpKQoKIyBQZXJmb3JtIHRoZSBzcGF0aWFsIGludGVyc2VjdGlvbiBmb3IgY291bnR5CnN0b3BzIDwtIHN0b3BzICU+JQogIHN0X2pvaW4oU0VQVEFfcmVnaW9uX21hcCwgbGVmdCA9IFRSVUUsIGpvaW4gPSBzdF9pbnRlcnNlY3RzKSAlPiUKICByZW5hbWUoY291bnR5ID0gQ09VTlRZX05BTSkgJT4lCiAgbXV0YXRlKGNlbnRlcl9jaXR5ID0gc3Rfd2l0aGluKHN0b3BzLCBjZW50ZXJfY2l0eSwgc3BhcnNlID0gRkFMU0UpKSU+JQogIG11dGF0ZShjZW50ZXJfY2l0eSA9IHJvd1N1bXMoY2VudGVyX2NpdHkpID4gMCkgICMgQ29udmVydCBsb2dpY2FsIG1hdHJpeCB0byB2ZWN0b3IKCiMgQ2F0ZWdvcml6ZSB0aGUgc3RvcHMKc3RvcHMgPC0gc3RvcHMgJT4lCiAgbXV0YXRlKGNhdGVnb3J5ID0gY2FzZV93aGVuKAogICAgY291bnR5ID09ICJQSElMQURFTFBISUEiICYgY2VudGVyX2NpdHkgPT0gVFJVRSB+ICJQSElMQURFTFBISUEtQ2VudGVyX0NpdHkiLAogICAgY291bnR5ID09ICJQSElMQURFTFBISUEiICYgY2VudGVyX2NpdHkgPT0gRkFMU0UgfiAiUEhJTEFERUxQSElBLU5vdF9DZW50ZXJfQ2l0eSIsCiAgICBUUlVFIH4gY291bnR5CiAgKSkgJT4lCiAgc2VsZWN0KC0iY2VudGVyX2NpdHkiKQogIApgYGAKCmBgYHtyIGhvdXJseSBzdG9wIGRhdGEsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUUsIHJlc3VsdHMgPSAnaGlkZSd9CiMgU0VUIFVQIEhPVVJMWSBBVkVSQUdFIFRSSVAgREFUQSBGT1IgRUFDSCBCVVMgU1RPUAoKZGF0X3RyaXBfY291bnRfaHIgPC0gZGF0ICU+JQogIGZpbHRlcihtb2RlICVpbiUgYygiQnVzIiwgIlRyb2xsZXlidXMiLCAiVHJvbGxleSIpKSAlPiUKICBncm91cF9ieShzdG9wX2lkLCBtb2RlLCBmaW5hbF9kYXlfdHlwZSkgJT4lCiAgc3VtbWFyaXNlKHRyaXBfY291bnQgPSBuKCksIAogICAgICAgICAgICBBbGxfUm91dGVzID0gcGFzdGUodW5pcXVlKHJvdXRlX2lkKSwgY29sbGFwc2UgPSAiLCAiKSwKICAgICAgICAgICAgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgbXV0YXRlKGF2Z190cmlwX2hyID0gcm91bmQodHJpcF9jb3VudC8yNCkpICU+JQogIG11dGF0ZShsb2dfYXZnX3RyaXBfaHIgPSByb3VuZChsb2cxcChhdmdfdHJpcF9ociksIGRpZ2l0cyA9IDApKSAlPiUKICBtdXRhdGUobWF4X2ZyZXEgPSBpZmVsc2UoYXZnX3RyaXBfaHIgPj0gMTIsICI1IE1BWCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSAoYXZnX3RyaXBfaHIgPj0gNiwgIjEwIE1BWCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSAoYXZnX3RyaXBfaHIgPj0gNCwgIjE1IE1BWCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoYXZnX3RyaXBfaHIgPj0gMiwgIjMwIE1BWCIsICI2MCBNQVgiKSkpKSkKCmRhdF90cmlwX2NvdW50X2hyIDwtIGxlZnRfam9pbihkYXRfdHJpcF9jb3VudF9ociwgc3RvcHMsIGJ5ID0gInN0b3BfaWQiKQoKZGF0X3RyaXBfY291bnRfaHIgPC0gc3RfYXNfc2YoZGF0X3RyaXBfY291bnRfaHIsIGNvb3JkcyA9IGMoInN0b3BfbG9uIiwgInN0b3BfbGF0IiksIGNycyA9IDQzMjYsIHJlbW92ZSA9IEZBTFNFKQoKIyBBc3N1bWluZyAnY291bnR5JyBpcyB0aGUgY29sdW1uIHdpdGggdGhlIGNvdW50eSBpbmZvcm1hdGlvbgpkYXRfdHJpcF9jb3VudF9ociA8LSBkYXRfdHJpcF9jb3VudF9ociAlPiUKICBtdXRhdGUoY2F0ZWdvcnkgPSBpZl9lbHNlKGNvdW50eSA9PSAiUEhJTEFERUxQSElBIiwgInVyYmFuIiwgInN1YnVyYmFuIikpCgojIFNpbXBsaWZ5IHRoZSBtYXggZnJlcXVlbmN5IGludG8gdHdvIGNhdGVnb3JpZXMKZGF0X3RyaXBfY291bnRfaHIgPC0gZGF0X3RyaXBfY291bnRfaHIgJT4lCiAgbXV0YXRlKHNpbXBsaWZpZWRfZnJlcSA9IGNhc2Vfd2hlbigKICAgIG1heF9mcmVxICVpbiUgYygiNSBNQVgiLCAiMTAgTUFYIiwgIjE1IE1BWCIpIH4gIjE1IG1pbnV0ZXMgb3IgbGVzcyIsCiAgICBUUlVFIH4gIk1vcmUgdGhhbiAxNSBtaW51dGVzIgogICkpCgojIFJlbW92ZSByb3dzIHdoZXJlICdjYXRlZ29yeScgaXMgTkEKZGF0X3RyaXBfY291bnRfaHIgPC0gZGF0X3RyaXBfY291bnRfaHIgJT4lIGZpbHRlcighaXMubmEoY2F0ZWdvcnkpKQoKIyBzdW0oZGF0X3RyaXBfY291bnRfaHIkdHJpcF9jb3VudCkgIzE5ODA1MDUgPC0gQWx3YXlzIG1ha2Ugc3VyZSB5b3UgcmV0YWluIHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb24KCmBgYAoKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KZ2dwbG90KGRhdF90cmlwX2J5X21vZGUsIGFlcyh4ID0gbW9kZSwgeSA9IG1vZGVfc2hhcmUsIGZpbGwgPSBtb2RlKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDAuNzUpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBidXNfcmV2b2x1dGlvbl9wYWxldHRlKGxlbmd0aCh1bmlxdWUoZGF0X3RyaXBfYnlfbW9kZSRtb2RlKSkpKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMChtb2RlX3NoYXJlLCAiJSAoIiwgbW9kZV9jb3VudCwgIiB0cmlwcykiKSksCiAgICAgICAgICAgIHZqdXN0ID0gLTAuNSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMi41KSArCiAgbGFicyh0aXRsZSA9ICJNb2RlIFNoYXJlIGJ5IFRyYW5zaXQgVHlwZSIsCiAgICAgICB4ID0gIk1vZGUiLAogICAgICAgeSA9ICJNb2RlIFNoYXJlICglKSIsCiAgICAgICBmaWxsID0gIk1vZGUiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCgojIyMgVW5yYXZlbGluZyB0aGUgRGlzcGFyaXRpZXMgaW4gQnVzIFNlcnZpY2UgRWZmaWNpZW5jeQoKVGhlIGRpc3Bhcml0aWVzIGluIGJ1cyBzZXJ2aWNlIGVmZmljaWVuY3kgYmV0d2VlbiB1cmJhbiBhbmQgc3VidXJiYW4gYXJlYXMgYXJlIHN0YXJrbHkgaGlnaGxpZ2h0ZWQgYnkgZnJlcXVlbmN5IGRhdGEuIEluIHN1YnVyYmFuIGFyZWFzLCB0aGUgbWFqb3JpdHkgb2YgYnVzIHN0b3BzIHN1ZmZlciBmcm9tIGluZnJlcXVlbnQgc2VydmljZXMuIFRoaXMgY29udHJhc3RzIHNoYXJwbHkgd2l0aCB1cmJhbiBhcmVhcywgd2hlcmUgYnVzIHN0b3BzIGdlbmVyYWxseSBwcm92aWRlIG1vcmUgZnJlcXVlbnQgc2VydmljZXMuIFRoZXNlIGRpZmZlcmVuY2VzIHVuZGVybGluZSBzaWduaWZpY2FudCBpbmVxdWl0aWVzIGluIHRyYW5zaXQgYWNjZXNzaWJpbGl0eSwgaW1wYWN0aW5nIGRhaWx5IGNvbW11dGVycyBsaWtlIE1pZGdlIHdobyByZWx5IGhlYXZpbHkgb24gdGhlc2Ugc2VydmljZXMuCgpJbiB0aGUgZm9sbG93aW5nIGxlYWZsZXQgbWFwLCB3ZSBpbGx1c3RyYXRlIHRoZXNlIGRpc3Bhcml0aWVzLiBZb3UnbGwgc2VlIHRoYXQgYnVzIHN0b3BzIGluIHN1YnVyYmFuIGFyZWFzIHByZWRvbWluYW50bHkgaGF2ZSBsb25nZXIgd2FpdGluZyB0aW1lcywgPHNwYW4gc3R5bGU9ImNvbG9yOiAjNjU1QkE2OyI+ZXhjZWVkaW5nIDE1IG1pbnV0ZXM8L3NwYW4+LCB3aGVyZWFzIHVyYmFuIHN0b3BzIHR5cGljYWxseSBoYXMgd2FpdGluZyB0aW1lIDxzcGFuIHN0eWxlPSJjb2xvcjogI0E2MTIzQTsiPnVuZGVyIDE1IG1pbnV0ZXM8L3NwYW4+LCBkZW1vbnN0cmF0aW5nIG1vcmUgZnJlcXVlbnQgc2VydmljZXMuIFRoaXMgdmlzdWFsIHJlcHJlc2VudGF0aW9uIGVtcGhhc2l6ZXMgdGhlIHVyZ2VudCBuZWVkIGZvciB0YXJnZXRlZCBpbXByb3ZlbWVudHMgaW4gc3VidXJiYW4gdHJhbnNpdCBzeXN0ZW1zIHRvIGJyaWRnZSB0aGUgZ2FwIGFuZCBlbmhhbmNlIG92ZXJhbGwgc2VydmljZSByZWxpYWJpbGl0eSBhbmQgZWZmaWNpZW5jeS4KCmBgYHtyIHNlcnZpY2UgcGVyaW9kIHN0b3AgZGF0YSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgY2FjaGU9RkFMU0V9CiMgU0VUIFVQIEFWRVJBR0UgVFJJUCBEQVRBIFBFUiBTRVJWSUNFIFBFUklPRCBGT1IgRUFDSCBCVVMgU1RPUAoKZGF0X3RyaXBfY291bnRfcHJkIDwtIGRhdCAlPiUKICBmaWx0ZXIobW9kZSAlaW4lIGMoIkJ1cyIsICJUcm9sbGV5YnVzIiwgIlRyb2xsZXkiKSkgJT4lCiAgZ3JvdXBfYnkoc3RvcF9pZCwgcGVha19jYXRlZ29yeSwgbW9kZSwgZmluYWxfZGF5X3R5cGUpICU+JQogIHN1bW1hcmlzZSh0cmlwX2NvdW50ID0gbigpLCAKICAgICAgICAgICAgQWxsX1JvdXRlcyA9IHBhc3RlKHVuaXF1ZShyb3V0ZV9pZCksIGNvbGxhcHNlID0gIiwgIiksCiAgICAgICAgICAgIC5ncm91cHMgPSAnZHJvcCcpICU+JQogIG11dGF0ZSgKICAgIGhvdXJzID0gZHVyYXRpb25zW3BlYWtfY2F0ZWdvcnldLAogICAgYXZnX3RyaXBfaHIgPSByb3VuZCh0cmlwX2NvdW50IC8gaG91cnMpCiAgKSAlPiUKICBzZWxlY3QoLWhvdXJzKSAlPiUKICBtdXRhdGUobG9nX2F2Z190cmlwX2hyID0gcm91bmQobG9nMXAoYXZnX3RyaXBfaHIpLCBkaWdpdHMgPSAwKSkgJT4lCiAgbXV0YXRlKG1heF9mcmVxID0gaWZlbHNlKGF2Z190cmlwX2hyID49IDEyLCAiNSBNQVgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UgKGF2Z190cmlwX2hyID49IDYsICIxMCBNQVgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UgKGF2Z190cmlwX2hyID49IDQsICIxNSBNQVgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGF2Z190cmlwX2hyID49IDIsICIzMCBNQVgiLCAiNjAgTUFYIikpKSkpCgpkYXRfdHJpcF9jb3VudF9wcmQgPC0gbGVmdF9qb2luKGRhdF90cmlwX2NvdW50X3ByZCwgc3RvcHMsIGJ5ID0gInN0b3BfaWQiKQoKZGF0X3RyaXBfY291bnRfcHJkIDwtIHN0X2FzX3NmKGRhdF90cmlwX2NvdW50X3ByZCwgY29vcmRzID0gYygic3RvcF9sb24iLCAic3RvcF9sYXQiKSwgY3JzID0gNDMyNiwgcmVtb3ZlID0gRkFMU0UpCgojIHN1bShkYXRfdHJpcF9jb3VudF9wcmQkdHJpcF9jb3VudCkgICMxOTgwNTA1IDwtIEFsd2F5cyBtYWtlIHN1cmUgeW91IHJldGFpbiB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9uCgpTRVBUQV9yZWdpb25fbWFwIDwtIHN0X3RyYW5zZm9ybShTRVBUQV9yZWdpb25fbWFwLCBzdF9jcnMoZGF0X3RyaXBfY291bnRfaHIpKQpgYGAKCmBgYHtyIGF2ZXJhZ2UgYnVzIGhvdXJseSBtYXhmcmVxLCBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBjYWNoZT1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KIyAjIERlZmluZSBjb2xvciBwYWxldHRlCiMgcGFsIDwtIGNvbG9yTnVtZXJpYyhwYWxldHRlID0gdmlyaWRpc0xpdGU6OnZpcmlkaXMoMjU2LCBvcHRpb24gPSAiQyIpLCBkb21haW4gPSBkYXRfdHJpcF9jb3VudF9ociRhdmdfdHJpcF9ocikKCiMgRGVmaW5lIHRoZSBjb2xvciBjb2RlcyBmb3IgYnVzIHJldm9sdXRpb24gYW5kIHJldmVyc2UgdGhlbQpidXNfcmV2b2x1dGlvbl9jb2xvcnMgPC0gcmV2KGMoIiNBNjEyM0EiLCAiIzY1NUJBNiIsICIjMjZBNjk5IiwgIiNGMkFFMkUiLCAiI0YyRTVENSIpKQoKIyBFbnN1cmUgbWF4X2ZyZXEgaXMgYSBmYWN0b3Igd2l0aCBsZXZlbHMgbWF0Y2hpbmcgdGhlIGNvbG9ycwpkYXRfdHJpcF9jb3VudF9ociRtYXhfZnJlcSA8LSBmYWN0b3IoZGF0X3RyaXBfY291bnRfaHIkbWF4X2ZyZXEsIGxldmVscyA9IGMoIjUgTUFYIiwgIjEwIE1BWCIsICIxNSBNQVgiLCAiMzAgTUFYIiwgIjYwIE1BWCIpKQoKIyBEZWZpbmUgdGhlIGNvbG9yIHBhbGV0dGUgZm9yIG1heF9mcmVxCm1heF9mcmVxX2NvbG9ycyA8LSBjKCI1IE1BWCIgPSAiIzRCMDA4MiIsICIxMCBNQVgiID0gIiNGRjQ1MDAiLCAiMTUgTUFYIiA9ICIjQTYxMjNBIiwgIjMwIE1BWCIgPSAiIzI2QTY5OSIsICI2MCBNQVgiID0gIiNGMkFFMkUiKQpwYWxfbWF4X2ZyZXEgPC0gY29sb3JGYWN0b3IocGFsZXR0ZSA9IG1heF9mcmVxX2NvbG9ycywgZG9tYWluID0gZGF0X3RyaXBfY291bnRfaHIkbWF4X2ZyZXEpCgojICMgR2VuZXJhdGUgdGhlIGxpc3QgZm9yIG92ZXJsYXlHcm91cHMgd2l0aCB0aGUgZGVzaXJlZCBvcmRlcgojIG92ZXJsYXlfZ3JvdXBzIDwtIGV4cGFuZC5ncmlkKGZpbmFsX2RheV90eXBlID0gYygiV2Vla2RheSIsICJXZWVrZW5kIiksIHBlYWtfY2F0ZWdvcnkgPSBwZWFrX29yZGVyKSAlPiUKIyAgIG11dGF0ZShncm91cF9uYW1lID0gcGFzdGUoZmluYWxfZGF5X3R5cGUsIHBlYWtfY2F0ZWdvcnksIHNlcCA9ICJfIikpICU+JQojICAgcHVsbChncm91cF9uYW1lKQoKIyAjIENyZWF0ZSB0aGUgbGVhZmxldCBtYXAKIyBtX2F2Z190cmlwX2hyIDwtIGxlYWZsZXQoKSAlPiUKIyAgIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuUG9zaXRyb24pICU+JQojICAgYWRkUG9seWdvbnMoZGF0YSA9IFNFUFRBX3JlZ2lvbl9tYXAsIGNvbG9yID0gImJsYWNrIiwgd2VpZ2h0ID0gMSwgZmlsbCA9IEZBTFNFKSAlPiUKIyAgIGFkZENpcmNsZU1hcmtlcnMoZGF0YSA9IGRhdF90cmlwX2NvdW50X2hyICU+JSBmaWx0ZXIoZmluYWxfZGF5X3R5cGUgPT0gIldlZWtkYXkiKSwKIyAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSAiV2Vla2RheSIsCiMgICAgICAgICAgICAgICAgICAgIGxuZyA9IH5zdG9wX2xvbiwgbGF0ID0gfnN0b3BfbGF0LAojICAgICAgICAgICAgICAgICAgICBjb2xvciA9IH5wYWxfbWF4X2ZyZXEobWF4X2ZyZXEpLAojICAgICAgICAgICAgICAgICAgICByYWRpdXMgPSAxLAojICAgICAgICAgICAgICAgICAgICBvcGFjaXR5ID0gMC44LAojICAgICAgICAgICAgICAgICAgICBwb3B1cCA9IH5wYXN0ZTAoIjxiPlN0b3AgSUQ6PC9iPiAiLCBzdG9wX2lkLCAiPGJyPiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGI+U3RvcCBOYW1lOjwvYj4gIiwgc3RvcF9uYW1lLCAiPGJyPiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGI+QXZnIEJ1c2VzL0hyOjwvYj4gIiwgYXZnX3RyaXBfaHIsICI8YnI+IiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8Yj5NYXggRnJlcXVlbmN5OjwvYj4gIiwgbWF4X2ZyZXEsICI8YnI+IiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8Yj5BbGwgUm91dGVzOjwvYj4gIiwgQWxsX1JvdXRlcywgIjxicj4iLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxiPkRheSBUeXBlOjwvYj4gIiwgZmluYWxfZGF5X3R5cGUpKSAlPiUKIyAgIGFkZENpcmNsZU1hcmtlcnMoZGF0YSA9IGRhdF90cmlwX2NvdW50X2hyICU+JSBmaWx0ZXIoZmluYWxfZGF5X3R5cGUgPT0gIldlZWtlbmQiKSwKIyAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSAiV2Vla2VuZCIsCiMgICAgICAgICAgICAgICAgICAgIGxuZyA9IH5zdG9wX2xvbiwgbGF0ID0gfnN0b3BfbGF0LAojICAgICAgICAgICAgICAgICAgICBjb2xvciA9IH5wYWxfbWF4X2ZyZXEobWF4X2ZyZXEpLAojICAgICAgICAgICAgICAgICAgICByYWRpdXMgPSAxLAojICAgICAgICAgICAgICAgICAgICBvcGFjaXR5ID0gMC44LAojICAgICAgICAgICAgICAgICAgICBwb3B1cCA9IH5wYXN0ZTAoIjxiPlN0b3AgSUQ6PC9iPiAiLCBzdG9wX2lkLCAiPGJyPiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGI+U3RvcCBOYW1lOjwvYj4gIiwgc3RvcF9uYW1lLCAiPGJyPiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGI+QXZnIEJ1c2VzL0hyOjwvYj4gIiwgYXZnX3RyaXBfaHIsICI8YnI+IiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8Yj5NYXggRnJlcXVlbmN5OjwvYj4gIiwgbWF4X2ZyZXEsICI8YnI+IiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8Yj5BbGwgUm91dGVzOjwvYj4gIiwgQWxsX1JvdXRlcywgIjxicj4iLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxiPkRheSBUeXBlOjwvYj4gIiwgZmluYWxfZGF5X3R5cGUpKSAlPiUKIyAgIGFkZExheWVyc0NvbnRyb2woCiMgICAgIG92ZXJsYXlHcm91cHMgPSBjKCJXZWVrZGF5IiwgIldlZWtlbmQiKSwKIyAgICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IEZBTFNFKQojICAgKSAlPiUKIyAgIGhpZGVHcm91cChjKCJXZWVrZW5kIikpICU+JQojICAgYWRkTGVnZW5kKHBhbCA9IHBhbF9tYXhfZnJlcSwgdmFsdWVzID0gZGF0X3RyaXBfY291bnRfaHIkbWF4X2ZyZXEsIHRpdGxlID0gIk1heCBGcmVxdWVuY3kiLAojICAgICAgICAgICAgIHBvc2l0aW9uID0gImJvdHRvbXJpZ2h0IikKIyAKIyBtX2F2Z190cmlwX2hyCmBgYAoKYGBge3IgYXZlcmFnZSBidXMgaG91cmx5IHNpbXBsaWZpZWQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPUZBTFNFfQojIERlZmluZSBjb2xvciBwYWxldHRlIGZvciBzaW1wbGlmaWVkIGZyZXF1ZW5jeSB1c2luZyB0aGUgYnVzIHJldm9sdXRpb24gY29sb3JzCnBhbCA8LSBjb2xvckZhY3RvcihjKCIjQTYxMjNBIiwgIiM2NTVCQTYiKSwgZG9tYWluID0gYygiMTUgbWludXRlcyBvciBsZXNzIiwgIk1vcmUgdGhhbiAxNSBtaW51dGVzIikpCgojIENyZWF0ZSB0aGUgbGVhZmxldCBtYXAKbV9hdmdfdHJpcF9ociA8LSBsZWFmbGV0KCkgJT4lCiAgYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkQ2FydG9EQi5Qb3NpdHJvbikgJT4lCiAgYWRkUG9seWdvbnMoZGF0YSA9IFNFUFRBX3JlZ2lvbl9tYXAsIGNvbG9yID0gImJsYWNrIiwgd2VpZ2h0ID0gMSwgZmlsbCA9IEZBTFNFKSAlPiUKICBhZGRDaXJjbGVNYXJrZXJzKAogICAgZGF0YSA9IGRhdF90cmlwX2NvdW50X2hyICU+JSBmaWx0ZXIoZmluYWxfZGF5X3R5cGUgPT0gIldlZWtkYXkiICYgIWlzLm5hKGNhdGVnb3J5KSksCiAgICBncm91cCA9IH5jYXRlZ29yeSwgICMgR3JvdXAgZGF0YSBiYXNlZCBvbiB1cmJhbiBvciBzdWJ1cmJhbgogICAgbG5nID0gfnN0b3BfbG9uLCAKICAgIGxhdCA9IH5zdG9wX2xhdCwKICAgIGNvbG9yID0gfnBhbChzaW1wbGlmaWVkX2ZyZXEpLCAgIyBDb2xvciBiYXNlZCBvbiBzaW1wbGlmaWVkIGZyZXF1ZW5jeQogICAgcmFkaXVzID0gMSwKICAgIG9wYWNpdHkgPSAwLjgsCiAgICBwb3B1cCA9IH5wYXN0ZTAoIjxiPlN0b3AgSUQ6PC9iPiAiLCBzdG9wX2lkLCAiPGJyPiIsCiAgICAgICAgICAgICAgICAgICAgIjxiPlN0b3AgTmFtZTo8L2I+ICIsIHN0b3BfbmFtZSwgIjxicj4iLAogICAgICAgICAgICAgICAgICAgICI8Yj5BdmcgQnVzZXMvSHI6PC9iPiAiLCBhdmdfdHJpcF9ociwgIjxicj4iLAogICAgICAgICAgICAgICAgICAgICI8Yj5NYXggRnJlcXVlbmN5OjwvYj4gIiwgc2ltcGxpZmllZF9mcmVxLCAiPGJyPiIsCiAgICAgICAgICAgICAgICAgICAgIjxiPkFsbCBSb3V0ZXM6PC9iPiAiLCBBbGxfUm91dGVzKQogICkgJT4lCiAgYWRkTGF5ZXJzQ29udHJvbCgKICAgIG92ZXJsYXlHcm91cHMgPSBjKCJ1cmJhbiIsICJzdWJ1cmJhbiIpLAogICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IEZBTFNFKQogICkgJT4lCiAgYWRkQ29udHJvbChodG1sID0gIjxkaXYgc3R5bGU9J2JhY2tncm91bmQtY29sb3I6IHdoaXRlOyBwYWRkaW5nOiA1cHg7Jz48c3Ryb25nPlNvdXJjZTo8L3N0cm9uZz4gU0VQVEEgR1RGUyBEYXRhIDIwMjQ8L2Rpdj4iLCBwb3NpdGlvbiA9ICJib3R0b21sZWZ0IikKCiMgRGlzcGxheSB0aGUgbWFwCm1fYXZnX3RyaXBfaHIKCmBgYAoKTWlkZ2XigJlzIGRhaWx5IGNoYWxsZW5nZSB3aXRoIGluY29uc2lzdGVudCBzdWJ1cmJhbiBidXMgc2VydmljZSByZWZsZWN0cyBicm9hZGVyIHRyYW5zaXQgaW5lcXVpdGllcyBiZXR3ZWVuIHVyYmFuIGFuZCBzdWJ1cmJhbiBzZXR0aW5ncy4gVGhpcyBkaXNwYXJpdHkgaXMgZXhlbXBsaWZpZWQgYnkgdGhlIG9wZXJhdGlvbmFsIGluZWZmaWNpZW5jaWVzIG9mIHN1YnVyYmFuIHJvdXRlcywgaGlnaGxpZ2h0ZWQgYnkgZGF0YSBpbmRpY2F0aW5nIHRoZXNlIGJ1c2VzIGZyZXF1ZW50bHkgZmFsbCB3aXRoaW4gdGhlIGxvd2VzdCAxNXRoIHBlcmNlbnRpbGUgZm9yIHNlcnZpY2UgcGVyZm9ybWFuY2UuIFRoaXMgbG93IHBlcmNlbnRpbGUgaW5kaWNhdGVzIHByb2xvbmdlZCB3YWl0IHRpbWVzIGFuZCB1bnJlbGlhYmxlIHNjaGVkdWxlc+KAlGZhY3RvcnMgY29udHJpYnV0aW5nIHRvIGhpZ2hlciBvcGVyYXRpb25hbCBjb3N0cyBhbmQgcmVkdWNlZCByZWxpYWJpbGl0eSBjb21wYXJlZCB0byBtb3JlIGVmZmljaWVudCB1cmJhbiBjb3VudGVycGFydHMuCgo8c3BhbiBzdHlsZT0iY29sb3I6ICM2NTVCQTY7Ij5TdWJ1cmJhbiBidXNlczwvc3Bhbj4sIGxpa2UgdGhlIHJvdXRlcyBNaWRnZSB1c2VzLCBvZnRlbiBzdWZmZXIgZHVlIHRvIGxvd2VyIHJpZGVyc2hpcCBkZW5zaXRpZXMgYW5kIGxlc3Mgb3B0aW1pemVkIHJvdXRlIHBsYW5uaW5nLCBhcyByZWZsZWN0ZWQgaW4gdGhlIHNpZ25pZmljYW50IG51bWJlciBvZiBzdWJ1cmJhbiByb3V0ZXMgbGlrZSBSb3V0ZXMgMTE4LCAxMjksIGFuZCA5MCB1bmRlcnBlcmZvcm1pbmcgaW4gdGhlIDE1dGggcGVyY2VudGlsZS4gVGhlc2Ugcm91dGVzJyBpbmVmZmljaWVuY2llcyBzdGFya2x5IGNvbnRyYXN0IHdpdGggdGhlIHJvYnVzdCB0cmFuc2l0IHN5c3RlbXMgaW4gdXJiYW4gYXJlYXMsIHVuZGVyc2NvcmluZyBhIGNyaXRpY2FsIGdhcCBpbiB0cmFuc2l0IGVxdWl0eSBhbmQgZWZmaWNpZW5jeSB0aGF0IGRlbWFuZHMgaW5ub3ZhdGl2ZSBzb2x1dGlvbnMuCgpgYGB7ciBzY2F0dGVycGxvdCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgY2FjaGU9RkFMU0V9Cgpyb3V0ZV9ldmFsdWF0aW9uIDwtIHJlYWQuY3N2KCJkYXRhL3JvdXRlX2V2YWx1YXRpb25fcmVwb3J0XzIwMTkuY3N2Iiwgc2VwID0gIjsiKQoKIyBDb252ZXJ0IENvc3QucGVyLlBhc3NlbmdlciBhbmQgUGFzc2VuZ2Vycy5wZXIuUmV2ZW51ZS5Ib3VyIGludG8gcHJvcGVyIG51bWVyaWMgY29sdW1ucwpyb3V0ZV9ldmFsdWF0aW9uJENvc3QucGVyLlBhc3NlbmdlciA8LSBhcy5udW1lcmljKGdzdWIoIlskLF0iLCAiIiwgcm91dGVfZXZhbHVhdGlvbiRDb3N0LnBlci5QYXNzZW5nZXIpKQpyb3V0ZV9ldmFsdWF0aW9uJFBhc3NlbmdlcnMucGVyLlJldmVudWUuSG91ciA8LSBhcy5udW1lcmljKHJvdXRlX2V2YWx1YXRpb24kUGFzc2VuZ2Vycy5wZXIuUmV2ZW51ZS5Ib3VyKQoKIyBDYWxjdWxhdGUgMTV0aCBwZXJjZW50aWxlIGZvciBQYXNzZW5nZXJzIGFuZCA4NXRoIHBlcmNlbnRpbGUgZm9yIENvc3QgKGR1ZSB0byByZXZlcnNlZCBheGlzKQpwYXNzZW5nZXJfMTV0aCA8LSBxdWFudGlsZShyb3V0ZV9ldmFsdWF0aW9uJFBhc3NlbmdlcnMucGVyLlJldmVudWUuSG91ciwgcHJvYnMgPSAwLjE1LCBuYS5ybSA9IFRSVUUpCmNvc3RfODV0aCA8LSBxdWFudGlsZShyb3V0ZV9ldmFsdWF0aW9uJENvc3QucGVyLlBhc3NlbmdlciwgcHJvYnMgPSAwLjg1LCBuYS5ybSA9IFRSVUUpCgojIERlZmluZSBjb2xvciBwYWxldHRlIGZvciB0aGUgdHlwZXMgb2YgYnVzZXMKcm91dGVfY29sb3JzIDwtIGMoIkNpdHkgQnVzIiA9ICIjQTYxMjNBIiwgIlN1YnVyYmFuIEJ1cyIgPSAiIzY1NUJBNiIpCnBhbCA8LSBjb2xvckZhY3Rvcihyb3V0ZV9jb2xvcnMsIGRvbWFpbiA9IHVuaXF1ZShyb3V0ZV9ldmFsdWF0aW9uJFR5cGUpKQoKIyBDcmVhdGUgdGhlIGdncGxvdApwIDwtIGdncGxvdChyb3V0ZV9ldmFsdWF0aW9uLCBhZXMoeCA9IFBhc3NlbmdlcnMucGVyLlJldmVudWUuSG91ciwgeSA9IENvc3QucGVyLlBhc3NlbmdlciwgY29sb3IgPSBUeXBlLCB0ZXh0ID0gcGFzdGUoIlJvdXRlOiIsIFJvdXRlLCAiPGJyPlBhc3NlbmdlcnMgcGVyIFJldmVudWUgSG91cjoiLCBQYXNzZW5nZXJzLnBlci5SZXZlbnVlLkhvdXIsICI8YnI+Q29zdCBwZXIgUGFzc2VuZ2VyOiIsIENvc3QucGVyLlBhc3NlbmdlciwgIjxicj5UeXBlOiIsIFR5cGUpKSkgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDAsIHhtYXggPSBwYXNzZW5nZXJfMTV0aCwgeW1pbiA9IG1heChyb3V0ZV9ldmFsdWF0aW9uJENvc3QucGVyLlBhc3NlbmdlciksIHltYXggPSBjb3N0Xzg1dGgsIGZpbGwgPSAibGlnaHRjb3JhbCIsIGFscGhhID0gMC4yKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gcGFzc2VuZ2VyXzE1dGgsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImdyZXkiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gY29zdF84NXRoLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmV5IikgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh0aXRsZSA9ICJQZXJmb3JtYW5jZSBvZiBTRVBUQSBDaXR5IEJ1cyBhbmQgU3VidXJiYW4gQnVzIiwKICAgICAgIHggPSAiUGFzc2VuZ2VycyBwZXIgUmV2ZW51ZSBIb3VyIiwKICAgICAgIHkgPSAiQ29zdCBwZXIgUGFzc2VuZ2VyIiwKICAgICAgIGNhcHRpb24gPSAiU291cmNlOiBTRVBUQSBGWSAyMDE5IFJlcG9ydCIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gcm91dGVfY29sb3JzKSArCiAgc2NhbGVfeV9yZXZlcnNlKGJyZWFrcyA9IHNlcSgwLCBtYXgocm91dGVfZXZhbHVhdGlvbiRDb3N0LnBlci5QYXNzZW5nZXIsIG5hLnJtID0gVFJVRSksIGJ5ID0gMSksCiAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGRvbGxhcl9mb3JtYXQocHJlZml4ID0gIiQiLCBzdWZmaXggPSAiIiwgYWNjdXJhY3kgPSAwLjAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgbWF4KHJvdXRlX2V2YWx1YXRpb24kUGFzc2VuZ2Vycy5wZXIuUmV2ZW51ZS5Ib3VyLCBuYS5ybSA9IFRSVUUpLCBieSA9IDEwKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gcGFzc2VuZ2VyXzE1dGggLyAyLCB5ID0gNi41LCBsYWJlbCA9ICIxNXRoIHBlcmNlbnRpbGUiLCBzaXplID0gMywgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNSkKCiMgQ29udmVydCB0byBwbG90bHkgZm9yIGFuIGludGVyYWN0aXZlIHBsb3Qgd2l0aCBkZXRhaWxlZCBob3ZlciBpbmZvcm1hdGlvbgpwX3Bsb3RseSA8LSBnZ3Bsb3RseShwLCB0b29sdGlwID0gInRleHQiKQoKIyBEaXNwbGF5IHRoZSBpbnRlcmFjdGl2ZSBwbG90CnBfcGxvdGx5CgpgYGAKCkFsdGhvdWdoIG1pY3JvdHJhbnNpdCBoYXMgYmVlbiBwcm9wb3NlZCBhcyBhbiBhbHRlcm5hdGl2ZSB0byBhZGRyZXNzIHRoZXNlIGluZWZmaWNpZW5jaWVzIGJ5IG9mZmVyaW5nIG1vcmUgYWRhcHRhYmxlIGFuZCBwb3RlbnRpYWxseSBlZmZpY2llbnQgc2VydmljZXMgaW4gbG93ZXItZGVuc2l0eSBhcmVhcywgaXRzIGVmZmVjdGl2ZW5lc3MgcmVtYWlucyBxdWVzdGlvbmFibGUuIEZvciBleGFtcGxlLCBBQyBUcmFuc2l0J3MgZXhwZXJpbWVudCBpbiBPYWtsYW5kIHRvIHJlcGxhY2UgZml4ZWQgcm91dGVzIHdpdGggbWljcm90cmFuc2l0IHJlc3VsdGVkIGluIGEgY29zdCBwZXIgcGFzc2VuZ2VyIHRoYXQgbW9yZSB0aGFuIGRvdWJsZWQsIGhpZ2hsaWdodGluZyB0aGUgY2hhbGxlbmdlcyBvZiBpbXBsZW1lbnRpbmcgc3VjaCBzZXJ2aWNlcyBlZmZlY3RpdmVseS5bXjldCgpUaGlzIGRhdGEgaWxsdXN0cmF0ZXMgdGhhdCB3aGlsZSBtaWNyb3RyYW5zaXQgaXMgb2Z0ZW4gdG91dGVkIGFzIGEgbW9kZXJuIHNvbHV0aW9uIGZvciBkZWNsaW5pbmcgcmlkZXJzaGlwLCBpdCBnZW5lcmFsbHkgZG9lcyBub3QgcGVyZm9ybSBhcyBlZmZpY2llbnRseSBhcyB0cmFkaXRpb25hbCBmaXhlZC1yb3V0ZSBzZXJ2aWNlcy4gVGhlIGNvcmUgZWZmaWNpZW5jeSBvZiBmaXhlZC1yb3V0ZSB0cmFuc2l0IGNvbWVzIGZyb20gaXRzIGFiaWxpdHkgdG8gY29uc29saWRhdGUgcmlkZXJzIGFsb25nIGEgcHJlZGljdGFibGUgcGF0aCwgbWluaW1pemluZyBkZXZpYXRpb25zIGFuZCBlbnN1cmluZyBjb25zaXN0ZW50IHRyYXZlbCB0aW1lcy4gSW4gY29udHJhc3QsIG1pY3JvdHJhbnNpdCdzIG9uLWRlbWFuZCBuYXR1cmUgY2FuIGxlYWQgdG8gc2lnbmlmaWNhbnQgaW5lZmZpY2llbmNpZXMsIHdpdGggcm91dGVzIGNvbnN0YW50bHkgY2hhbmdpbmcgdG8gYWNjb21tb2RhdGUgaW5kaXZpZHVhbCBwaWNrdXAgcmVxdWVzdHMsIGxlYWRpbmcgdG8gaW5jcmVhc2VkIHRyYXZlbCB0aW1lcyBhbmQgb3BlcmF0aW9uYWwgY29zdHMuCgpHaXZlbiB0aGVzZSBjaGFsbGVuZ2VzLCBpdCBtaWdodCBiZSBtb3JlIHBydWRlbnQgdG8gZXhwbG9yZSBvdGhlciBhbHRlcm5hdGl2ZXMsIHN1Y2ggYXMgZGVwbG95aW5nIHNtYWxsZXIsIGZpeGVkLXJvdXRlIG1pbmlidXNzZXMgZHVyaW5nIHBlYWsgaG91cnMgdG8gZW5oYW5jZSBjb25uZWN0aXZpdHkgYW5kIG1hbmFnZSBjcm93ZGluZyBtb3JlIGVmZmVjdGl2ZWx5LiBUaGlzIGFwcHJvYWNoIGNvdWxkIGxldmVyYWdlIHRoZSBsb3dlciBvcGVyYXRpb25hbCBjb3N0cyBvZiBzbWFsbGVyIHZlaGljbGVzIHdoaWxlIG1haW50YWluaW5nIHRoZSBzdHJ1Y3R1cmVkIGVmZmljaWVuY3kgb2YgZml4ZWQtcm91dGUgdHJhbnNpdCwgcG90ZW50aWFsbHkgb2ZmZXJpbmcgYSBtb3JlIHN1c3RhaW5hYmxlIHNvbHV0aW9uIHRvIHRoZSBzdWJ1cmJhbiB0cmFuc2l0IHdvZXMgdGhhdCBNaWRnZSBhbmQgY291bnRsZXNzIG90aGVycyBmYWNlIGRhaWx5LgoKW145XTogW1VyZ28gMjAxOV0oaHR0cHM6Ly93d3cuYXB0YS5jb20vd3AtY29udGVudC91cGxvYWRzL0NvbmZlcmVuY2VzX01lZXRpbmdzX0V2ZW50cy9QcmVzZW50YXRpb25zLzIwMTgtU3VzdGFpbmFiaWxpdHkvVXJnby1Kb2huLnBkZiNwYWdlPTI0KQoKYGBge3Igc3RhdGljIHNjYXR0ZXJwbG90LCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQojICMgQXNzdW1pbmcgcGFzc2VuZ2VyXzE1dGggYW5kIGNvc3RfODV0aCBhcmUgeW91ciBjYWxjdWxhdGVkIDE1dGggcGVyY2VudGlsZSB2YWx1ZXMKIyBnZ3Bsb3Qocm91dGVfZXZhbHVhdGlvbiwgYWVzKHggPSBQYXNzZW5nZXJzLnBlci5SZXZlbnVlLkhvdXIsIHkgPSBDb3N0LnBlci5QYXNzZW5nZXIsIGNvbG9yID0gVHlwZSkpICsKIyAgICMgQWRkIGEgcmVjdGFuZ2xlIGFuZCB0ZXh0IGFubm90YXRpb24gZm9yIHRoZSAxNXRoIHBlcmNlbnRpbGUKIyAgIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDAsIHhtYXggPSBwYXNzZW5nZXJfMTV0aCwgeW1pbiA9IG1heChyb3V0ZV9ldmFsdWF0aW9uJENvc3QucGVyLlBhc3NlbmdlciksIHltYXggPSBjb3N0Xzg1dGgsCiMgICAgICAgICAgICBmaWxsID0gInJlZCIsIGFscGhhID0gMC4yKSArCiMgICBnZW9tX3BvaW50KCkgKwojICAgbGFicyh0aXRsZSA9ICJQZXJmb3JtYW5jZSBvZiBTRVBUQSBDaXR5IEJ1cyBhbmQgU3VidXJiYW4gQnVzIiwKIyAgICAgICAgeCA9ICJQYXNzZW5nZXJzIHBlciBSZXZlbnVlIEhvdXIiLAojICAgICAgICB5ID0gIkNvc3QgcGVyIFBhc3NlbmdlciIpICsKIyAgIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNldDEiKSArCiMgICBzY2FsZV95X3JldmVyc2UoYnJlYWtzID0gc2VxKDAsIG1heChyb3V0ZV9ldmFsdWF0aW9uJENvc3QucGVyLlBhc3NlbmdlciwgbmEucm0gPSBUUlVFKSwgYnkgPSAxKSwKIyAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBkb2xsYXJfZm9ybWF0KHByZWZpeCA9ICIkIiwgc3VmZml4ID0gIiIsIGFjY3VyYWN5ID0gMC4wMSkpICsKIyAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgbWF4KHJvdXRlX2V2YWx1YXRpb24kUGFzc2VuZ2Vycy5wZXIuUmV2ZW51ZS5Ib3VyLCBuYS5ybSA9IFRSVUUpLCBieSA9IDEwKSkgKwojICAgdGhlbWVfbWluaW1hbCgpICsKIyAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IHBhc3Nlbmdlcl8xNXRoLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmV5IikgKwojICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gY29zdF84NXRoLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmV5IikgKwojICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKwojICAgYW5ub3RhdGUoInRleHQiLCB4ID0gcGFzc2VuZ2VyXzE1dGggLyAyLCB5ID0gNi41LCBsYWJlbCA9ICIxNXRoIHBlcmNlbnRpbGUiLAojICAgICAgICAgICAgc2l6ZSA9IDMsIGNvbG9yID0gImJsYWNrIikKYGBgCgoKIyMjIEltcGFjdCBhbmQgSW5ub3ZhdGlvbjogRW5oYW5jaW5nIFN1YnVyYmFuIEJ1cyBTZXJ2aWNlcwoKV2hpbGUgdGhlIHJhdyBkYXRhIGlsbHVtaW5hdGVzIHRoZSBzZXJ2aWNlIGRpc3Bhcml0aWVzLCB0aGUgdHJ1ZSBkZXB0aCBvZiB0aGlzIGlzc3VlIGlzIGJlc3QgY2FwdHVyZWQgdGhyb3VnaCB0aGUgbGl2ZWQgZXhwZXJpZW5jZXMgb2Ygc3VidXJiYW4gY29tbXV0ZXJzIGxpa2UgTWlkZ2UuIFBlcnNvbmFsIHN0b3JpZXMgcmV2ZWFsIHRoZSBicm9hZGVyIGh1bWFuIGltcGFjdDogbWlzc2VkIG9wcG9ydHVuaXRpZXMsIHByb2xvbmdlZCB3b3JrZGF5cywgYW5kIGRpbWluaXNoZWQgZmFtaWx5IGxpZmUgZHVlIHRvIGluZnJlcXVlbnQgYnVzIHNlcnZpY2VzLiBUaGlzIHF1YWxpdGF0aXZlIGluc2lnaHQgcGFpbnRzIGEgdml2aWQgcGljdHVyZSBvZiB0aGUgZGFpbHkgY2hhbGxlbmdlcyBhbmQgdW5kZXJzY29yZXMgdGhlIHVyZ2VuY3kgZm9yIHRhcmdldGVkIGltcHJvdmVtZW50cy4KClNFUFRBJ3Mgb25nb2luZyAiQnVzIFJldm9sdXRpb24iIHByb2plY3QgYWltcyB0byBtb2Rlcm5pemUgYW5kIGVuaGFuY2UgYnVzIHNlcnZpY2VzLCBwcm9taXNpbmcgdXBkYXRlZCByb3V0ZXMgYW5kIGltcHJvdmVkIGZyZXF1ZW5jaWVzIHRoYXQgaGF2ZW4ndCBiZWVuIHJldmlzZWQgc2luY2UgdGhlIDE5NjBzLiBXaGlsZSB0aGUgaW5pdGlhdGl2ZSBzZWVrcyB0byByZWR1Y2UgaGVhZHdheXMgdG8gYSBtYXhpbXVtIG9mIDMwIG1pbnV0ZXMgZXZlbiBpbiB0aGUgbW9zdCByZW1vdGUgc3VidXJiYW4gYXJlYXMsIGl0IGhhcyBmYWNlZCBkZWxheXMgYW5kIGNyaXRpY2lzbSwgcGFydGljdWxhcmx5IGNvbmNlcm5pbmcgaXRzIHBvdGVudGlhbCB0byBkaXNwcm9wb3J0aW9uYXRlbHkgaW1wYWN0IGxvdy1pbmNvbWUgbmVpZ2hib3Job29kcy4gVGhpcyB0ZW5zaW9uIGhpZ2hsaWdodHMgdGhlIGNvbXBsZXggaW50ZXJwbGF5IGJldHdlZW4gaW1wcm92aW5nIHNlcnZpY2UgZWZmaWNpZW5jeSBhbmQgYWRkcmVzc2luZyBjb21tdW5pdHkgY29uY2VybnMgb2YgZ2VudHJpZmljYXRpb24uCgpBcyB3ZSBjb25jbHVkZSBvdXIgZXhwbG9yYXRpb24gb2Ygc3VidXJiYW4gYnVzIHRyYW5zaXQgZGlzcGFyaXRpZXMgaW4gUGhpbGFkZWxwaGlhLCB0aGUgY29tcGVsbGluZyBuYXJyYXRpdmVzIG9mIGRhaWx5IGNvbW11dGVycywgdW5kZXJwaW5uZWQgYnkgcm9idXN0IFNFUFRBIGRhdGEsIHBhaW50IGEgY2xlYXIgcGljdHVyZSBvZiB0aGUgY2hhbGxlbmdlcyBhbmQgdGhlIHVyZ2VudCBuZWVkIGZvciBzeXN0ZW1pYyBpbXByb3ZlbWVudHMuIFRoZSAiQnVzIFJldm9sdXRpb24iIHByb2plY3QsIHdoaWxlIGEgcHJvbWlzaW5nIHN0ZXAgdG93YXJkIGVuaGFuY2luZyBidXMgZnJlcXVlbmNpZXMgYW5kIHVwZGF0aW5nIGRlY2FkZXMtb2xkIHJvdXRlcywgYWxzbyBoaWdobGlnaHRzIHRoZSBkZWxpY2F0ZSBiYWxhbmNlIHJlcXVpcmVkIHRvIGltcHJvdmUgc2VydmljZSBlZmZpY2llbmN5IHdpdGhvdXQgZXhhY2VyYmF0aW5nIHNvY2lhbCBpbmVxdWl0aWVzLgoKRW1icmFjaW5nIGlubm92YXRpdmUgc29sdXRpb25zIGFuZCBmb3N0ZXJpbmcgY29tbXVuaXR5IGVuZ2FnZW1lbnQgaW4gdHJhbnNpdCBwbGFubmluZyBhcmUgY3J1Y2lhbC4gQnkgY29tbWl0dGluZyB0byBib3RoIHRlY2hub2xvZ2ljYWwgdXBncmFkZXMgYW5kIGVxdWl0YWJsZSBzZXJ2aWNlIGRpc3RyaWJ1dGlvbiwgU0VQVEEgY2FuIGVuc3VyZSB0aGF0IGV2ZXJ5IGNvbW11dGVyLCByZWdhcmRsZXNzIG9mIHdoZXJlIHRoZXkgbGl2ZSwgaGFzIHJlbGlhYmxlIGFuZCB0aW1lbHkgYWNjZXNzIHRvIHB1YmxpYyB0cmFuc2l0LiBUaGlzIG5vdCBvbmx5IGltcHJvdmVzIGluZGl2aWR1YWwgZGFpbHkgZXhwZXJpZW5jZXMgYnV0IGFsc28gc3VwcG9ydHMgYnJvYWRlciBnb2FscyBvZiBlY29ub21pYyBtb2JpbGl0eSBhbmQgc3VzdGFpbmFibGUgdXJiYW4gZGV2ZWxvcG1lbnQuCgpBcyBzdGFrZWhvbGRlcnMsIHdlIGFyZSBjYWxsZWQgdXBvbiB0byBzdXBwb3J0IHRoZXNlIGluaXRpYXRpdmVzLCBhZHZvY2F0ZSBmb3IgdHJhbnNwYXJlbnQgYW5kIGluY2x1c2l2ZSBwbGFubmluZyBwcm9jZXNzZXMsIGFuZCBlbnN1cmUgdGhhdCB0aGUgdm9pY2VzIG9mIGFsbCBjb21tdXRlcnMsIGVzcGVjaWFsbHkgdGhvc2UgbW9zdCBhZmZlY3RlZCBsaWtlIE1pZGdlLCBhcmUgaGVhcmQgYW5kIGFkZHJlc3NlZCBpbiB0aGUgcHVyc3VpdCBvZiBhIHRydWx5IGNvbm5lY3RlZCBhbmQgZXF1aXRhYmxlIHRyYW5zaXQgc3lzdGVtLg==